博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Codeforces Round #246 (Div. 2) D. Prefixes and Suffixe 后缀数组
阅读量:4699 次
发布时间:2019-06-09

本文共 2490 字,大约阅读时间需要 8 分钟。

链接:

题意:

给你一个字符串,求每一个和前缀匹配的后缀在这个字符串中出现的次数

题解:

先算出lcp,找到sa[i]==0的位置标记为beg,和前缀匹配的后缀一定会出现beg的左边,这个想一想明白了

我们先算出beg左边每一个后缀和beg匹配的长度,beg右边的先放到一个vector中,便于之后二分查找

我们从beg向左遍历,对于每一个dp[i],如果dp[i]==n-sa[i],就可以更新结果了,从i到beg中间的都满足,同时还要加上beg右边的

代码:

31 int n, k; 32 int Rank[MAXN], tmp[MAXN]; 33 int sa[MAXN], lcp[MAXN]; 34  35 bool compare_sa(int i, int j) { 36     if (Rank[i] != Rank[j]) return Rank[i] < Rank[j]; 37     else { 38         int ri = i + k <= n ? Rank[i + k] : -1; 39         int rj = j + k <= n ? Rank[j + k] : -1; 40         return ri < rj; 41     } 42 } 43  44 void construct_sa(string S, int *sa) { 45     n = S.length(); 46     for (int i = 0; i <= n; i++) { 47         sa[i] = i; 48         Rank[i] = i < n ? S[i] : -1; 49     } 50     for (k = 1; k <= n; k *= 2) { 51         sort(sa, sa + n + 1, compare_sa); 52         tmp[sa[0]] = 0; 53         for (int i = 1; i <= n; i++) 54             tmp[sa[i]] = tmp[sa[i - 1]] + (compare_sa(sa[i - 1], sa[i]) ? 1 : 0); 55         for (int i = 0; i <= n; i++) Rank[i] = tmp[i]; 56     } 57 } 58  59 void construct_lcp(string S, int *sa, int *lcp) { 60     int n = S.length(); 61     for (int i = 0; i <= n; i++) Rank[sa[i]] = i; 62     int h = 0; 63     lcp[0] = 0; 64     for (int i = 0; i < n; i++) { 65         int j = sa[Rank[i] - 1]; 66         if (h > 0) h--; 67         for (; j + h < n && i + h < n; h++) 68             if (S[j + h] != S[i + h]) break; 69         lcp[Rank[i] - 1] = h; 70     } 71 } 72  73 int dp[MAXN]; 74  75 int main() { 76     ios::sync_with_stdio(false), cin.tie(0); 77     string s; 78     cin >> s; 79     construct_sa(s, sa); 80     construct_lcp(s, sa, lcp); 81     int beg; 82     rep(i, 0, n + 1) if (sa[i] == 0) { 83         beg = i; 84         break; 85     } 86     memset(dp, 0x3f, sizeof(dp)); 87     dp[beg] = INF; 88     per(i, 0, beg) dp[i] = min(dp[i + 1], lcp[i]); 89     rep(i, beg + 1, n + 1) dp[i] = min(dp[i - 1], lcp[i - 1]); 90     VI v; 91     rep(i, beg + 1, n + 1) if (dp[i]) v.pb(dp[i]); 92     sort(all(v)); 93     map
mmp; 94 per(i, 0, beg) { 95 if (!dp[i]) break; 96 if (dp[i] == n - sa[i]) { 97 mmp[dp[i]] += beg - i + 1; 98 mmp[dp[i]] += v.end() - lower_bound(all(v), dp[i]); 99 }100 }101 cout << mmp.size() + 1 << endl;102 for (auto it : mmp) cout << it.first << ' ' << it.second << endl;103 cout << n << ' ' << 1 << endl;104 return 0;105 }

 

转载于:https://www.cnblogs.com/baocong/p/7525618.html

你可能感兴趣的文章
pip 警告!The default format will switch to columns in the future
查看>>
Arrays类学习笔记
查看>>
实验吧之【天下武功唯快不破】
查看>>
2019-3-25多线程的同步与互斥(互斥锁、条件变量、读写锁、自旋锁、信号量)...
查看>>
win7-64 mysql的安装
查看>>
dcm4chee 修改默认(0002,0013) ImplementationVersionName
查看>>
maven3在eclipse3.4.2中创建java web项目
查看>>
发布时间 sql语句
查看>>
黑马程序员 ExecuteReader执行查询
查看>>
记一些从数学和程序设计中体会到的思想
查看>>
题目1462:两船载物问题
查看>>
POJ 2378 Tree Cutting(树形DP,水)
查看>>
第二冲刺阶段个人博客5
查看>>
UVA 116 Unidirectional TSP (白书dp)
查看>>
第三方测速工具
查看>>
MySQL 网络访问连接
查看>>
在aws ec2上使用root用户登录
查看>>
数据访问 投票习题
查看>>
cnblog!i'm coming!
查看>>
使用点符号代替溢出的文本
查看>>