LRJ书上例题,但是自己在思考过程中挺有收获。。。。
UVA1401题目直达
题目大意是拆解字符串,有几种方法。
简单思路:设 dp[i] 为字符串从第i位开始的拆解方法;仔细一想的话就会发现这样的关系:
dp[i]=∑j∈[1,S]dp[i+len[j]]
其中
S 为单词总数,j为单词编号。
使用trie可以实现,AC代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
const int maxn=500000;
const int mod=20071027;
char buffer[maxn];
int dp[maxn];
int mark[maxn];
char word[5000][200];
int n;
int val[maxn];
int ch[maxn][27];
int sz;
void ini()
{
sz=1;
memset(val,0,sizeof(val));
memset(ch,0,sizeof(ch));
memset(dp,0,sizeof(dp));
memset(mark,0,sizeof(mark));
memset(word,0,sizeof(word));
}
int ind(char c)
{
return c-'a';
}
void insert(char *s,int v)
{
int len=strlen(s);
int u=0;
for(int i=0;i<len;i++)
{
int num=ind(s[i]);
if(!ch[u][num])
{
ch[u][num]=sz;
sz++;
}
u=ch[u][num];
}
val[u]=v;
}
bool queryeach(char *s)
{
int parent=0;
int len=strlen(s);
for(int i=0;i<len;i++)
{
int num=ind(s[i]);
if(ch[parent][num]==0)
{
return false;
}
parent=ch[parent][num];
}
return (val[parent]>0);
}
vector<int > query(char *s)
{
int parent=0;
vector<int > ans;
int len=strlen(s);
for(int i=0;i<len;i++)
{
int num=ind(s[i]);
if(!ch[parent][num])
{
break;
}
if(val[ch[parent][num]]!=0)
{
ans.push_back(val[ch[parent][num]]);
}
parent=ch[parent][num];
}
/* for(unsigned i=0;i<ans.size();i++) { printf("%d ",ans[i]); } printf("\n"); */
return ans;
}
char kagami[maxn];
int main()
{
//freopen("1.out","w",stdout);
int cas=0;
while(~scanf("%s",buffer))
{
cas++;
scanf("%d",&n);
ini();
int maxlen=0;
for(int i=0;i<n;i++)
{
memset(kagami,0,sizeof(kagami));
scanf("%s",kagami);
int len=strlen(kagami);
mark[len]++;
maxlen=max(maxlen,len);
strcpy(word[i],kagami);
insert(kagami,len);
}
//初始化
int len=strlen(buffer);
for(int i=1;i<=maxlen;i++)
{
if(mark[i]>0)
{
bool flag=queryeach(buffer+len-i);
if(flag)
{
dp[len-i]=(dp[len-i]+1+mod)%mod;
}
}
}
/* for(int i=0;i<=len;i++) { printf("dp[%d]=%d\n",i,dp[i]); } printf("\n"); */
dp[len]=0;
for(int i=len-1;i>=0;i--)
{
vector<int> res=query(buffer+i);
/* for(unsigned j=0;j<res.size();j++) { printf("res[%d]=%d\n",j,res[j]); } printf("\n"); */
for(unsigned j=0;j<res.size();j++)
{
dp[i]=(dp[i]+dp[i+res[j]]+mod)%mod;
}
}
/* for(int i=0;i<=len;i++) { printf("dp[%d]=%d\n",i,dp[i]); } */
printf("Case %d: %d\n",cas,(dp[0]+mod)%mod);
}
return 0;
}
调了一段时间,不过收获还是比较大的。