poj3415Common Substrings(好题)
来源:互联网 发布:免费开源网管软件 编辑:程序博客网 时间:2024/05/06 12:28
Common Substrings
Time Limit: 5000MS Memory Limit: 65536KTotal Submissions: 8519 Accepted: 2812
Description
A substring of a string T is defined as:
Given two strings A, B and one integer K, we defineS, a set of triples (i, j, k):
You are to give the value of |S| for specific A, B andK.
Input
The input file contains several blocks of data. For each block, the first line contains one integerK, followed by two lines containing strings A and B, respectively. The input file is ended byK=0.
1 ≤ |A|, |B| ≤ 105
1 ≤ K ≤ min{|A|, |B|}
Characters of A and B are all Latin letters.
Output
For each case, output an integer |S|.
Sample Input
2aababaaabaabaa1xxxx0
Sample Output
225
Source
POJ Monthly--2007.10.06, wintokk
论文题,
基本思路是计算 A 的所有后缀和 B 的所有后缀之间的最长公共前缀的长度,
把最长公共前缀长度不小于 k 的部分全部加起来。先将两个字符串连起来,中间
用一个没有出现过的字符隔开。按 height 值分组后,接下来的工作便是快速的
统计每组中后缀之间的最长公共前缀之和。扫描一遍,每遇到一个 B 的后缀就统
计与前面的 A 的后缀能产生多少个长度不小于 k 的公共子串, 这里 A 的后缀需要
用一个单调的栈来高效的维护。然后对 A 也这样做一次。(摘自论文)
论文题,
基本思路是计算 A 的所有后缀和 B 的所有后缀之间的最长公共前缀的长度,
把最长公共前缀长度不小于 k 的部分全部加起来。先将两个字符串连起来,中间
用一个没有出现过的字符隔开。按 height 值分组后,接下来的工作便是快速的
统计每组中后缀之间的最长公共前缀之和。扫描一遍,每遇到一个 B 的后缀就统
计与前面的 A 的后缀能产生多少个长度不小于 k 的公共子串, 这里 A 的后缀需要
用一个单调的栈来高效的维护。然后对 A 也这样做一次。(摘自论文)
#include <map>#include <set>#include <stack>#include <queue>#include <cmath>#include <ctime>#include <vector>#include <cstdio>#include <cctype>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>using namespace std;#define INF 0x3f3f3f3f#define inf -0x3f3f3f3f#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define mem0(a) memset(a,0,sizeof(a))#define mem1(a) memset(a,-1,sizeof(a))#define mem(a, b) memset(a, b, sizeof(a))typedef long long ll;const int maxn=200000+100;char s[maxn],s1[maxn];int st[maxn][2];int sa[maxn],t[maxn],t2[maxn],c[maxn],n;//构造字符串s的后缀数组,每个字符值必须为0~m-1void build_sa(int m){ int *x=t,*y=t2; //基数排序 for(int i=0;i<m;i++) c[i]=0; for(int i=0;i<n;i++) c[x[i]=s[i]]++; for(int i=1;i<m;i++) c[i]+=c[i-1]; for(int i=n-1;i>=0;i--) sa[--c[x[i]]]=i; for(int k=1;k<=n;k<<=1){ int p=0; //直接利用sa数组排序第二关键字 for(int i=n-k;i<n;i++) y[p++]=i; for(int i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k; //基数排序第一关键字 for(int i=0;i<m;i++) c[i]=0; for(int i=0;i<n;i++) c[x[y[i]]]++; for(int i=1;i<m;i++) c[i]+=c[i-1]; for(int i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i]; //根据sa和y计算新的x数组 swap(x,y); p=1; x[sa[0]]=0; for(int i=1;i<n;i++) x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++; if(p>=n) break; m=p; //下次基数排序的最大值 }}int rank1[maxn],height[maxn];void getHeight(){ int i,j,k=0; for(i=0;i<=n;i++) rank1[sa[i]]=i; for(i=0;i<n;i++){ if(k) k--; int j=sa[rank1[i]-1]; while(s[i+k]==s[j+k]) k++; height[rank1[i]]=k; }}int main(){ int k; while(scanf("%d",&k)!=EOF){ if(k==0) break; scanf("%s%s",&s,&s1); int l1=strlen(s); s[l1]='&'; s[l1+1]='\0'; strcat(s,s1); n=strlen(s); s[n++]='0'; build_sa(128); n--; getHeight(); ll sum=0; ll tot=0,top=0; for(int i=1;i<=n;i++){ //表示排名 int cnt=0; if(height[i]<k){ tot=0; top=0; } else{ if(sa[i-1]<l1){ tot+=(height[i]-k+1); cnt++; } while(top>0&&height[i]<=st[top-1][0]){ top--; tot-=st[top][1]*(st[top][0]-height[i]); cnt+=st[top][1]; } st[top][0]=height[i]; st[top++][1]=cnt; //st[top][1]表示这个区间内含有多少个sa小于l1的 if(sa[i]>l1) sum+=tot; } } tot=0,top=0; for(int i=1;i<=n;i++){ //表示排名 int cnt=0; if(height[i]<k){ tot=0; top=0; } else{ if(sa[i-1]>l1){ tot+=(height[i]-k+1); cnt++; } while(top>0&&height[i]<=st[top-1][0]){ top--; tot-=st[top][1]*(st[top][0]-height[i]); cnt+=st[top][1]; } st[top][0]=height[i]; st[top++][1]=cnt; if(sa[i]<l1) sum+=tot; } } printf("%I64d\n",sum); } return 0;}
0 0
- poj3415Common Substrings(好题)
- poj3415Common Substrings(后缀数组+单调栈)
- UVA 10829 L-Gap Substrings(后缀数组好题)
- poj 1226 Substrings kmp 好题,我调试了一晚上啊!!汗
- Substrings
- Substrings
- Substrings
- Substrings
- Substrings
- Substrings
- Substrings
- CodeForces 550A Two Substrings 简单题
- [后缀自动机 模板题] SPOJ 8222 Substrings
- hdu--4455+ Substrings+2012杭州区域赛C题+DP
- HDU 1238 Substrings 字符串水题,STL String 的应用
- LeetCode 467 Unique Substrings in Wraparound String (思维题)
- 每周LeetCode算法题(十二): 647. Palindromic Substrings
- POJ1226 Substrings
- HDU1018
- 微软面试题
- thinkphp验证码操作方法的书写及验证码的生成及使用
- Xcode 7请求网络报错
- codeforces 479E E. Riding in a Lift(dp+段修改的优化)
- poj3415Common Substrings(好题)
- centos和rhel的软件安装方法rpm和yum
- 使用cwRsync实现windows下文件定时同步
- 【Android】wifi开发
- win7交换机共享宽带连接上网
- 我开通博客了
- javascript BOM 浏览器对象模型
- 现在准备看《金赛性学报告》
- MyString类实现