首页 > 代码库 > SPOJ 7758. Growing Strings (ac自动机+dp)
SPOJ 7758. Growing Strings (ac自动机+dp)
题目大意:
给出了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 1000005 using 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)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。