标签:car fine its get div clu anti ret 增加
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3966 Accepted Submission(s): 1316
#include <stdio.h> #include <algorithm> #include <iostream> #include <string.h> #include <queue> #include <string> using namespace std; #define INF 0x3f3f3f3f struct node { int x; string a; }dp[55][1500]; int maxx; string maxstr; string b; char str[110][15]; int val[110]; struct Trie { int Next[1500][26];//26是这里讨论26个小写字母的情况,根据情况修改 int fail[1500],end[1500];//end数组表示以该节点结尾的字符串的数量 int root,L;//L用来标记节点序号,以广度优先展开的字典树的序号 int newnode() //建立新节点 { for(int i = 0;i < 26;i++) Next[L][i] = -1; //将该节点的后继节点域初始化 end[L++] = 0; return L-1; //返回当前节点编号 } void init() //初始化操作 { L = 0; root = newnode(); } void insert(char buf[],int val) { int len = strlen(buf); int now = root; for(int i = 0;i < len;i++) { if(Next[now][buf[i]-‘a‘] == -1) //如果未建立当前的后继节点,建立新的节点 Next[now][buf[i]-‘a‘] = newnode(); now = Next[now][buf[i]-‘a‘]; } end[now]+=val;//以该节点结尾的字符串数量增加1 } void build() { queue<int>Q; //用广度优先的方式,将树层层展开 fail[root] = root; for(int i = 0;i < 26;i++) if(Next[root][i] == -1) Next[root][i] = root; else { fail[Next[root][i]] = root; Q.push(Next[root][i]); } while( !Q.empty() ) { int now = Q.front(); Q.pop(); end[now]+=end[fail[now]]; for(int i = 0;i < 26;i++) if(Next[now][i] == -1) Next[now][i] = Next[fail[now]][i];//该段的最后一个节点匹配后,跳到拥有最大公共后缀的fail节点继续匹配 else { fail[Next[now][i]]=Next[fail[now]][i];//当前节点的fail节点等于它前驱节点的fail节点的后继节点 Q.push(Next[now][i]); } } } int query(char buf[]) { int len = strlen(buf); int now = root; int res = 0; for(int i = 0;i < len;i++) { now = Next[now][buf[i]-‘a‘]; int temp = now; while( temp != root ) { res += end[temp];//加上以当前节点结尾的字符串数 end[temp] = 0;//该题是防止计算重复的字符串 temp = fail[temp];//每次找最大公共后缀对应的fail节点 } } return res; } void solve(int len) { for(int i=0;i<=len;i++) for(int j=0;j<L;j++){ dp[i][j].x=INF; dp[i][j].a.clear(); } dp[0][0].x=0; for(int i=0;i<len;i++) for(int j=0;j<L;j++) { if(dp[i][j].x<INF) { for(int k=0;k<26;k++) { int news=Next[j][k]; if(dp[i+1][news].x==INF||dp[i+1][news].x<dp[i][j].x+end[news]) { dp[i+1][news].x=dp[i][j].x+end[news]; dp[i+1][news].a=dp[i][j].a+(char)(‘a‘+k); } else if(dp[i+1][news].x==dp[i][j].x+end[news]&&((dp[i+1][news].a.size()>dp[i][j].a.size()+1)||((dp[i+1][news].a.size()==dp[i][j].a.size()+1)&&dp[i+1][news].a>(dp[i][j].a+(char)(‘a‘+k))))) { dp[i+1][news].x=dp[i][j].x+end[news]; dp[i+1][news].a=dp[i][j].a+(char)(‘a‘+k); } } } } maxx=0; maxstr=""; for(int i=1;i<=len;i++) for(int j=0;j<L;j++) { if(dp[i][j].x<INF){ if((maxx<dp[i][j].x)||(maxx==dp[i][j].x&&dp[i][j].a.size()<maxstr.size())||(maxx==dp[i][j].x&&dp[i][j].a.size()==maxstr.size()&&dp[i][j].a<maxstr)){ maxx=dp[i][j].x; maxstr=dp[i][j].a; } } } } void debug() { for(int i = 0;i < L;i++) { printf("id = %3d,fail = %3d,end = %3d,chi = [",i,fail[i],end[i]); for(int j = 0;j < 26;j++) printf("%2d",Next[i][j]); printf("\n"); } } }; char buf[1500]; Trie ac; int main() { int t,n,ans,m; scanf("%d",&t); while(t--) { ac.init(); scanf("%d%d",&n,&m); for(int i=0;i<m;i++) scanf("%s",str[i]); for(int i=0;i<m;i++){ scanf("%d",&val[i]); ac.insert(str[i],val[i]); } ac.build(); ac.solve(n); cout<<maxstr<<endl; } return 0; }
标签:car fine its get div clu anti ret 增加
原文地址:http://www.cnblogs.com/a249189046/p/7581847.html