POJ3415Common Substrings(后缀自动机)

A substring of a string T is defined as:

                Tik)= TiTi +1... Ti+k -1, 1≤ i≤ i+k-1≤| T|.

Given two strings AB and one integer K, we define S, a set of triples (ijk):

                S = {( ijk) | k≥ KAik)= Bjk)}.

You are to give the value of |S| for specific AB 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

题意:

找出S,T两串中所有相同的长度大于等于K的字符串。不判重,即位置不同的相同串要重复统计。

解法:

  • 已知,对于一个串S,后缀自动机可以得到其所有的子串,以及递推出不同字串出现的数量num。
  • 对于匹配串T,一个字符一个字符的走一趟自动机(假设现在走到了T[i]),可以得到S中以T[i]结尾的集合,然后用集合中满足>=k的元素乘以num。
  • 里面有拓扑关系,用了lazy标记。
  • 加了输入优化,时间排名第三。

注意:

ans=ans+(long long)lazy[p]*(maxlen[p]-max(K,maxlen[slink[p]]+1)+1)*num[p];

开始把long long的位置写错了,wa了很多次。

错误位置:ans=(long long)ans+lazy[p]*(maxlen[p]-max(K,maxlen[slink[p]]+1)+1)*num[p];

 (难道是先执行乘法,这个时候long long无效?)

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<memory>
#include<algorithm>
using namespace std;
const int maxn=201000;
int K;char chr[maxn];
struct SAM
{
    int sz,Last,ch[maxn][52],slink[maxn],maxlen[maxn];
    int c[maxn],pos[maxn],num[maxn],lazy[maxn];
    //num表示一个模板串S中x集合出现的次数,lazy表示匹配串T中x集合的累加(向上slink(fa)传递)。 
    //pos是拓扑排序后的结果,用来递推num和lazy。 
    long long ans;
    int get(char x)
    {
        if(x>='a'&&x<='z') return x-'a';
        return x-'A'+26;
    }
    void init()
    {
        sz=0; Last=sz=1;
        memset(ch[1],0,sizeof(ch[1]));
        num[1]=lazy[1]=0;
    }
    void add(int x)
    {
          int np=++sz,p=Last;Last=np;
          lazy[sz]=0;num[sz]=1;
          maxlen[np]=maxlen[p]+1;
          memset(ch[np],0,sizeof(ch[np]));
          while(p&&!ch[p][x]) ch[p][x]=np,p=slink[p];
          if(!p) slink[np]=1;
          else {                
                int q=ch[p][x];
                if(maxlen[q]==maxlen[p]+1)  slink[np]=q;
                else {                
                    int nq=++sz; lazy[sz]=num[sz]=0;
                    memcpy(ch[nq],ch[q],sizeof(ch[q]));
                    slink[nq]=slink[q],slink[np]=slink[q]=nq;
                    maxlen[nq]=maxlen[p]+1;
                    while(p&&ch[p][x]==q) ch[p][x]=nq,p=slink[p];
                }
         }      
    }
    void sort()
    {
        for(int i=0;i<=sz;i++) c[i]=0;
        for(int i=1;i<=sz;i++) c[maxlen[i]]++;
        for(int i=1;i<=sz;i++) c[i]+=c[i-1];
        for(int i=1;i<=sz;i++) pos[c[maxlen[i]]--]=i;
        for(int i=sz;i>=1;i--) num[slink[pos[i]]]+=num[pos[i]];
    }
    void solve()
    {        
        char c=getchar();    
        while(!(c>='a'&&c<='z')&&!(c>='A'&&c<='Z')) c=getchar();
        int mp=1,Len=0;ans=0;
        while((c>='a'&&c<='z')||(c>='A'&&c<='Z')) {
            int x=get(c);c=getchar();
            if(ch[mp][x]){ Len++;  mp=ch[mp][x];}
            else {
                while(mp&&!ch[mp][x]) mp=slink[mp];
                if(!mp) {  mp=1; Len=0; }//~
                else { Len=maxlen[mp]+1; mp=ch[mp][x]; }
            }
            if(Len>=K) {
                ans=(long long)ans+(Len-max(maxlen[slink[mp]]+1,K)+1)*num[mp];
                if(maxlen[slink[mp]]>=K)  lazy[slink[mp]]++;
            }
        }
        for(int i=sz;i>=1;i--) {
            int p=pos[i];
            ans=ans+(long long)lazy[p]*(maxlen[p]-max(K,maxlen[slink[p]]+1)+1)*num[p];
            if(maxlen[slink[p]]>=K) lazy[slink[p]]+=lazy[p];
        }
        printf("%lld
",ans);
    }
};
SAM sam;
int main()
{
    while(~scanf("%d",&K)){
        if(K==0) return 0;
        sam.init();
        char c=getchar();    
        while(!(c>='a'&&c<='z')&&!(c>='A'&&c<='Z')) c=getchar();
        while((c>='a'&&c<='z')||(c>='A'&&c<='Z')) sam.add(sam.get(c)),c=getchar();
        sam.sort(); 
        sam.solve();
    }
    return 0;
} 
原文地址:https://www.cnblogs.com/hua-dong/p/7995256.html