標籤:os io ar for sp amp on new c
題目大意:
給出了N個串。問最多有多少個串組成的序列,是可以由上一個串通過左右兩邊加字元構成的。
思路分析:
在trie上的dp
在建立自動機的時候,得到fail的同時,用dp記錄這個串作為最後一個串所可以得到的最多的滿足要求的串的數量。
那麼 dp[i] = max(dp[i在trie上的的父親節點],dp[i的fail節點] )+ 以i節點結尾的單詞的數量,注意不是以i字元結尾。
#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <queue>#define maxn 1000005using namespace std;const char tab = 'a';const int max_next = 26;int next[maxn][max_next],fail[maxn],num[maxn],dp[maxn],siz;int newnode(){ for(int i=0;i<max_next;i++) next[siz][i]=0; fail[siz]=num[siz]=dp[siz]=0; return siz++;}void Insert(char *s,int len){ int p=0; for(int i=0;i<len;i++) { int &x=next[p][s[i]-tab]; p=x?x:x=newnode(); } num[p]++;}int ans=0;void acbuild(){ queue<int>Q; Q.push(0); while(!Q.empty()) { int temp=Q.front(); Q.pop(); for(int i=0;i<max_next;i++) { int v=next[temp][i]; if(v==0)next[temp][i]=next[fail[temp]][i]; else Q.push(v); if(temp!=0)fail[v]=next[fail[temp]][i]; dp[v]=max(dp[temp],dp[fail[v]])+num[v]; ans=max(ans,dp[v]); } }}int query(char *s,int len){ int cnt=0; for(int i=0,p=0;i<len;i++) { p=next[p][s[i]-tab]; for(int f=p;f;f=fail[f]){ if(num[f]>0)cnt++; } } return cnt;}char word[maxn];int main(){ int N; while(scanf("%d",&N)!=EOF && N) { ans=0; siz=0; newnode(); for(int i=1;i<=N;i++) { scanf("%s",word); Insert(word,strlen(word)); } acbuild(); printf("%d\n",ans); } return 0;}
SPOJ 7758. Growing Strings (ac自動機+dp)