求字符串不同子串个数
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了求字符串不同子串个数相关的知识,希望对你有一定的参考价值。
各位大虾,请教求字符串不同子串个数的高效算法,越详细越好,我先谢谢了
参考技术A 百度SAM,很复杂马拉车算法——求回文子串个数zoj4110
zoj的测评姬好能卡时间。。
求回文子串的个数:只要把p[i]/2就行了:
如果s_new[i]是‘#’,算的是没有中心的偶回文串
反之是奇回文串
/* 给定两个字符串s,t 结论:s,t不相同的第一个字符下标为l,最后一个字符下标为r 如果l==r,那么不存在解 如果l<r,那么翻转s的一个子串时,一定是将s[l]和s[r]互相翻转 反证:假设存在s[l]和s[r+k]的翻转方法, 因为s[r+k]=t[r+k]=t[l],且s[l]=t[r+k],可得s[l]=t[l],矛盾 l-k同理 所以本题只需要考虑三种情况: 1.两个串相等:求s的回文子串 2.l==r,无解 3.l<r,首先s[l,r]翻转后和t[l,r]相等,然后找以s[l,r]为中心的回文子串 */ #include<bits/stdc++.h> using namespace std; #define maxn 5000006 char s[maxn],t[maxn],s_new[maxn]; int p[maxn]; int init(){ int len=strlen(s),j=2; s_new[0]=‘$‘,s_new[1]=‘#‘; for(int i=0;i<len;i++){ s_new[j++]=s[i]; s_new[j++]=‘#‘; } s_new[j]=0; return j; } long long manacher(){ long long res=0; int len=init(),mx=0,id; for(int i=0;i<len;i++){ if(mx>i)p[i]=min(p[2*id-i],mx-i); else p[i]=1; while(s_new[i-p[i]]==s_new[i+p[i]])p[i]++; if(mx<i+p[i])mx=i+p[i],id=i; res+=(long long )p[i]/2; } return res; } int main(){ int T;cin>>T; while(T--){ scanf("%s%s",s,t); int len=strlen(s),l=0x3f3f3f3f,r=0; for(int i=0;i<len;i++) if(s[i]!=t[i]){l=i;break;} for(int i=len-1;i>=0;i--) if(s[i]!=t[i]){r=i;break;} if(l==r){puts("0");continue;} if(l>r){cout<<manacher()<<endl;continue;} int flag=0; for(int i=l,j=r;i<=r;i++,j--) if(s[i]!=t[j])flag=1; if(flag){puts("0");continue;} else { int ans=1; while(l!=0 && r!=len-1){ --l;++r; if(s[l]==s[r])ans++; else break; } cout<<ans<<endl; } } }
以上是关于求字符串不同子串个数的主要内容,如果未能解决你的问题,请参考以下文章