SPOJ LCS2 Longest Common Substring 2[后缀自动机+dp]

题意:

求n个串的最长公共子串,n<=10

思路:

不会啊orz

先放一波参考资料&题解好了。

codeforces_Understanding Suffix Automaton in depth

code风景区_spoj_lcs2

code风景区_sam教学

candy SPOJ 1812 LCS2 [后缀自动机 DP]

首先参考下2个串的LCS的做法spoj-lcs

卧槽终于懂了…

一个串在上面走的时候记录与每个状态公共子串的最大值,注意**出现次数向父亲传递**,一个状态能到达说明了Suffix Link指向的状态可以取到最大子串,这一步对val后基数排序然后倒着更新就行了

…代码之后补

关键是理解这句话:一个状态能到达说明了Suffix Link指向的状态可以取到最大子串

比如如果状态S(从初始状态到S状态所表示的子串是abcbc) 能够最长向前匹配的长度是x,那么状态s的par的状态Q(从初始状态到Q状态所表示的子串是bc)也至少为x.

所以dp[link[v]] = Max{dp[link[v]],dp[v]}

妈个鸡。。。

没事改什么字符集大小啊。。。

上道题做的是数字。。就手贱把字符集的大小改成了12.。。忘了改回来。。WA到死。。。

  1/* ***********************************************
  2Author :111qqz
  3Created Time :2017年11月08日 星期三 18时50分18秒
  4File Name :4436.cpp
  5************************************************ */
  6
  7#include <bits/stdc++.h>
  8#define PB push_back
  9#define fst first
 10#define sec second
 11#define lson l,m,rt<<1
 12#define rson m+1,r,rt<<1|1
 13#define ms(a,x) memset(a,x,sizeof(a))
 14typedef long long LL;
 15#define pi pair < int ,int >
 16#define MP make_pair
 17
 18using namespace std;
 19const double eps = 1E-8;
 20const int dx4[4]={1,0,0,-1};
 21const int dy4[4]={0,-1,1,0};
 22const int inf = 0x3f3f3f3f;
 23#define MAXALP 30
 24const int mod = 2012;
 25struct state
 26{
 27    int len, link, nxt[MAXALP];
 28};
 29const int N =1E5+7;
 30state st[N*2];
 31int sz, last,rt;
 32char s[N];
 33int cnt[2*N],rk[2*N];//for radix sort
 34int dp[2*N],maxlen[2*N];
 35void sa_init()
 36{
 37    sz = 0;
 38    last = rt = ++sz;
 39    st[1].len = 0;
 40    st[1].link=-1;
 41    ms(st[1].nxt,-1);
 42}
 43void sa_extend(int c)
 44{
 45    int cur = ++sz;
 46    st[cur].len = st[last].len + 1;
 47    memset(st[cur].nxt, -1, sizeof(st[cur].nxt));
 48    int p;
 49    for (p = last; p != -1 && st[p].nxt[c] == -1; p = st[p].link)
 50        st[p].nxt[c] = cur;
 51    if (p == -1) {
 52        st[cur].link = rt;
 53    } else {
 54        int q = st[p].nxt[c];
 55        if (st[p].len + 1 == st[q].len) {
 56            st[cur].link = q;
 57        } else {
 58            int clone = ++sz ;
 59            st[clone].len = st[p].len + 1;
 60            st[clone].link = st[q].link;
 61            memcpy(st[clone].nxt, st[q].nxt, sizeof(st[q].nxt));
 62            for (; p != -1 && st[p].nxt[c] == q; p = st[p].link)
 63                st[p].nxt[c] = clone;
 64            st[q].link = st[cur].link = clone;
 65        }
 66    }
 67    last = cur;
 68}
 69void topo()
 70{
 71    ms(cnt,0); 
 72    for (int i = 1 ; i <= sz ; i++) cnt[st[i].len]++;
 73    for ( int i = 1 ; i <= sz ; i++) cnt[i]+=cnt[i-1];
 74    for (int i = 1 ; i <= sz  ;i++) rk[cnt[st[i].len]--] = i;
 75}
 76char ST[N];
 77int main()
 78{
 79#ifndef  ONLINE_JUDGE 
 80        freopen("./in.txt","r",stdin);
 81#endif
 82
 83    int flag = 1;
 84    ms(maxlen,0x3f);
 85    while (scanf("%s",ST)!=EOF)
 86    {
 87//  cout<<"ST:"<<ST<<endl;
 88    if (flag)
 89    {
 90        sa_init();
 91        for (int i = 0,len = strlen(ST);  i < len ; i++)
 92        {
 93        sa_extend(ST[i]-'a');
 94        }
 95        topo();
 96        flag = 0 ;
 97    }
 98    else
 99    {
100        ms(dp,0);
101        int now = rt,len = 0;
102        for ( int i = 0,_len = strlen(ST) ; i < _len ; i++)
103        {
104        if (st[now].nxt[ST[i]-'a']!=-1)
105        {
106            now = st[now].nxt[ST[i]-'a'];
107            len++;
108            dp[now] = max(dp[now],len);
109          //  printf("now:%d dp[now]:%d len: %d\n",now,dp[now],len);
110        }
111        else 
112        {
113            while (now!=-1&&st[now].nxt[ST[i]-'a']==-1) now = st[now].link;
114            if (now==-1) now=rt,len=0;else len = st[now].len + 1,now=st[now].nxt[ST[i]-'a'],dp[now] = max(dp[now],len);
115        }
116        }
117        for ( int i = sz ; i >= 1 ; i-- )
118        {
119        int v = rk[i];
120        st[v].len = min(st[v].len,dp[v]);
121        dp[st[v].link] = max(dp[st[v].link],dp[v]);
122//      dp[v] = 0 ;  //其实只是为了清空,多次ms太慢了...
123        }
124    }
125
126    }
127
128    int ans = 0 ;
129    for ( int i = 1 ; i <= sz ; i++) ans = max(ans,st[i].len);
130    printf("%d\n",ans);
131//  cout<<ans<<endl;
132
133
134
135#ifndef ONLINE_JUDGE  
136    fclose(stdin);
137#endif
138    return 0;
139}