poj 3415 Common Substrings(2个字符串大于等于m的子串数量 后缀数组)
2017-09-19 15:54
483 查看
Common Substrings
Description
A substring of a string T is defined as:
T(i, k)=TiTi+1...Ti+k-1, 1≤i≤i+k-1≤|T|.
Given two strings A, B and one integer K, we define S, a set of triples (i, j, k):
S = {(i, j, k) | k≥K, A(i, k)=B(j, k)}.
You are to give the value of |S| for specific A, B and K.
Input
The input file contains several blocks of data. For each block, the first line contains one integer K, followed by two lines containing strings A and B, respectively. The input file is ended by K=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
Sample Output
解题报告:http://blog.csdn.net/acm_cxlove/article/details/7946967
因为两个字符串的最大前缀长度等于他们之间的最大前缀的最小值 所以用单调栈维护一个上升的最大前缀长度 更新栈时 减去超过当前最大长度的贡献
扫两次 一次用B去匹配前面的A 一次用A去匹配前面的B
Time Limit: 5000MS | Memory Limit: 65536K | |
Total Submissions: 11375 | Accepted: 3760 |
A substring of a string T is defined as:
T(i, k)=TiTi+1...Ti+k-1, 1≤i≤i+k-1≤|T|.
Given two strings A, B and one integer K, we define S, a set of triples (i, j, k):
S = {(i, j, k) | k≥K, A(i, k)=B(j, k)}.
You are to give the value of |S| for specific A, B and K.
Input
The input file contains several blocks of data. For each block, the first line contains one integer K, followed by two lines containing strings A and B, respectively. The input file is ended by K=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
2 aababaa abaabaa 1 xx xx 0
Sample Output
22 5
解题报告:http://blog.csdn.net/acm_cxlove/article/details/7946967
因为两个字符串的最大前缀长度等于他们之间的最大前缀的最小值 所以用单调栈维护一个上升的最大前缀长度 更新栈时 减去超过当前最大长度的贡献
扫两次 一次用B去匹配前面的A 一次用A去匹配前面的B
#include <iostream> #include <stdio.h> #include <string.h> #include <stack> #include <queue> #include <map> #include <set> #include <vector> #include <math.h> #include <bitset> #include <algorithm> #include <climits> using namespace std; const int N = 1000000+10; typedef long long LL; int sa ; int t1 ,t2 ,c ; int rank1 ,height ; void build_sa(int s[],int n,int m) { int i,j,p,*x=t1,*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=0; i<m; i++) c[i]+=c[i-1]; for(int i=n-1; i>=0; i--) sa[--c[x[i]]]=i; for(j=1; j<=n; j<<=1) { p=0; for(i=n-j; i<n; i++) y[p++]=i; for(i=0; i<n; i++) if(sa[i]>=j) y[p++]=sa[i]-j; for(i=0; i<m; i++) c[i]=0; for(i=0; i<n; i++) c[x[y[i]]]++; for(i=0; i<m; i++) c[i]+=c[i-1]; for(i=n-1; i>=0; i--) sa[--c[x[y[i]]]]=y[i]; swap(x,y); p=1; x[sa[0]]=0; for(i=1; i<n; i++) x[sa[i]]=(y[sa[i-1]]==y[sa[i]])&&(y[sa[i-1]+j]==y[sa[i]+j])?p-1:p++; if(p>=n) break; m=p; } } int s ; void getheight(int s[],int n) { int i, j, k=0; for(i=0; i<=n; i++) rank1[sa[i]]=i; for(i=0; i<n; i++) { if(k) k--; j=sa[rank1[i]-1]; while(s[i+k]==s[j+k]) k++; height[rank1[i]]=k; } return ; } char str ; LL st [2]; int main() { int m; while(scanf("%d", &m),m!=0) { int n=0; scanf("%s",str); int len1=strlen(str); for(int i=0; i<len1; i++) s[n++]=str[i]; s ='#'; n++; scanf("%s",str); int len2=strlen(str); for(int i=0; i<len2; i++) s[n++]=str[i]; s =0; build_sa(s,n+1,300); getheight(s,n); int k=0; LL sum=0, ans=0; for(int i=1;i<=n;i++) { if(height[i]<m) { k=0,sum=0; continue; } int cnt=0; if(sa[i-1]<len1) cnt++,sum+=(height[i]-m+1); while(k>=1&&height[i]<=st[k][0]) { cnt+=st[k][1]; sum-=(st[k][1]*(st[k][0]-height[i])); k--; } st[++k][1]=cnt; st[k][0]=height[i]; if(sa[i]>len1) ans+=sum; } sum=0,k=0; for(int i=1;i<=n;i++) { if(height[i]<m) { k=0,sum=0; continue; } int cnt=0; if(sa[i-1]>len1) cnt++,sum+=(height[i]-m+1); while(k>=1&&height[i]<=st[k][0]) { cnt+=st[k][1]; sum-=(st[k][1]*(st[k][0]-height[i])); k--; } st[++k][1]=cnt; st[k][0]=height[i]; if(sa[i]<len1) ans+=sum; } printf("%lld\n",ans); } return 0; }
相关文章推荐
- POJ 3415-Common Substrings(后缀数组+单调栈-公共子串的长度)
- poj 3415 Common Substrings(长度大于k的相同子串对数xian 后缀数组+单调桟统计)
- poj 3415 :长度不小于 k 的公共子串的个数(后缀数组+单调栈)
- POJ3294--Life Forms 后缀数组+二分答案 大于k个字符串的最长公共子串
- POJ 题目3415 Common Substrings(后缀数组+栈,求可以匹配到的长度大于k的公共子串个数)
- 输入整数(n是小于9位数的整数),当作字符串处理, 看是否有相同的子串,如1212,相同子串是12, 141516则没有子串(子串长度必须大于等于2)。 若
- poj 3415 后缀数组 两个字符串中长度不小于 k 的公共子串的个数
- POJ - 3415 Common Substrings 求2个串大于K的公共子串个数
- poj 1226 Substrings 求n个字符串的最长公共子串(这里可以是反序相同) 后缀数组
- poj 3294 Life Forms 求n(n>1)个字符串的最长的一个子串 后缀数组
- 后缀数组(多个字符串的最长公共子串)—— POJ 3294
- POJ 3415 Life Forms 给定n个字符串,求出现在不小于k个字符串中的最长子串。
- poj2774 后缀数组2个字符串的最长公共子串
- poj 2774 最长公共子串--字符串hash或者后缀数组或者后缀自动机
- POJ 3415 Common Substrings(长度不小于k 的公共子串的个数--后缀数组+单调栈优化)
- POJ 3415 求两个字符串间长度不小于k的公共子串的个数
- poj 2774 Long Long Message 求两个字符串的最长公共子串 后缀数组
- POJ 3415 Common Substrings (求长度不小于k的公共子串的个数)
- (Relax 后缀数组1.4)POJ 2774 Long Long Message(求两个字符串公共子串的最大长度)
- poj 3415 Common Substrings(后缀数组+单调栈)