最近做了不字符串的题,做下小结吧~
首先是Trie(也叫前缀树),Trie的结构并不难理解,Trie是个树形结构,它的每条边对应一个字符,每个节点对应一个字符串的前缀(根节点对应空串),将给定的字符串建立起一棵Trie以后,查找一个串的复杂度就是O(L)的。在对应的节点处可以做各种标记,根据不同的情况有不同的用法,代码也很好写,不过Trie的空间要求比较大……下面贴几道题。。。。
hdu 1671 Phone List
给出一堆串,问是否有的串是另一个串的前缀。。比较简单的题吧,在每个单词结尾的节点打个标记,然后插入的时候判断是否到达某一个节点的末尾,当插入的单词到结尾时判断是否还能走就ok了
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn=100000+10;
int ch[maxn][10],val[maxn],size;
char str[20];
void Init()
{
memset(ch[0],0,sizeof(ch[0]));
val[0]=0;size=0;
}
bool Insert(const char *s)
{
int u=0,n=strlen(s);
for(int i=0;i<n;++i)
{
int c=str[i]-'0';
if(!ch[u][c])
{
ch[u][c]=++size;
memset(ch[size],0,sizeof(ch[size]));
val[size]=0;
}
else if(i==n-1) return false;
u=ch[u][c];
if(val[u]) return false;
}
val[u]=1;
return true;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int t;
scanf("%d",&t);
while(t--)
{
int n;
bool flag=true;
Init();
scanf("%d",&n);
for(int i=0;i<n;++i)
{
scanf("%s",str);
flag=flag&&Insert(str);
}
if(flag) puts("YES");
else puts("NO");
}
return 0;
}
UVALive 3942 Remember the Word(Trie+DP)
给出n个字典串和一个长串,把这个字符串分解成若干个单词连接,有多少种方法。
不错的题,先建立字典树,然后DP搞之。
题解:
http://blog.csdn.net/qian99/article/details/18730455
UVA 11732 strcmp() Anyone
给出一个strcmp()函数,再给出n个字符串,问这n个字符串使用给出的函数两两比较,总共需要比较的次数。也是不错的题,把字符串边插入边计算即可,做了这题会让你对Trie的结构理解的更深一点。比较坑爹的是时限比较严,用了左儿子右兄弟表示法才过掉……
题解:
http://blog.csdn.net/qian99/article/details/18735485
UVA 11488 Hyper Prefix Sets(Trie)
给出n个串,问这n个串的公共前缀乘字符个数的最大值。这题跟上一题差不多,也是边插入边算就行了。
题解:
http://blog.csdn.net/qian99/article/details/18736843
接下来就是KMP了,KMP网上资料非常多,也就不多说了(省得丢人啊)……
hdu 2087 剪花布条
给出两个串A和B,问B在A中的匹配次数(不重叠)。
比较简单的KMP应用吧,构造完next数组后去匹配,和普通匹配不同的是,匹配成功以后不能退出,而是答案+1,并且将状态置0,接着匹配。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn=1000+10;
char s1[maxn],s2[maxn];
int next[maxn],ans;
void Kmp()
{
int n=strlen(s1);
int m=strlen(s2);
if(m>n) return ;
int j=0;
for(int i=0;i<n;++i)
{
while(j&&s1[i]!=s2[j]) j=next[j];
if(s1[i]==s2[j]) j++;
if(j==m) {ans++;j=0;}
}
}
void getnext()
{
int n=strlen(s2);
next[0]=next[1]=0;
for(int i=1;i<n;++i)
{
int j=next[i];
while(j&&s2[i]!=s2[j]) j=next[j];
next[i+1]=(s2[i]==s2[j])?j+1:0;
}
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
while(~scanf("%s",s1))
{
if(s1[0]=='#') break;
scanf("%s",s2);
ans=0;
getnext();
Kmp();
printf("%d\n",ans);
}
return 0;
}
hdu 3336 Count the string
给出一个字符串,问它的所有前缀和它匹配的次数。其实KMP求出的next函数是一个状态转移的函数,当发生转移时,如果转移到0,此时是空串,如果不是,那么说明当前状态和前面是有匹配的。
题解:
http://blog.csdn.net/qian99/article/details/18768235
hdu 3746 Cyclic Nacklace
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn=2000+10;
double p[110],dp[maxn][110];
bool vis[maxn][110];
int ch[maxn][63],val[maxn],next[maxn],size,n;
int idx(char c)
{
if(c>='0'&&c<='9') return c-'0';
if(c>='a'&&c<='z') return c-'a'+10;
return c-'A'+10+26;
}
void Init()
{
memset(vis,0,sizeof(vis));
memset(ch[0],0,sizeof(ch[0]));
memset(next,0,sizeof(next));
memset(val,0,sizeof(val));
memset(p,0,sizeof(p));
size=0;
}
void insert(const char *s)
{
int u=0,len=strlen(s);
for(int i=0;i<len;++i)
{
int c=idx(s[i]);
if(!ch[u][c])
{
ch[u][c]=++size;
memset(ch[size],0,sizeof(ch[size]));
val[size]=0;
}
u=ch[u][c];
}
val[u]=1;
}
void build()
{
queue<int>q;
for(int i=0;i<62;++i)
{
if(ch[0][i]) q.push(ch[0][i]);
}
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=0;i<62;++i)
{
int v=ch[u][i];
if(!v) {ch[u][i]=ch[next[u]][i];continue;}
q.push(v);
int j=next[u];
while(j&&!ch[j][i]) j=next[j];
next[v]=ch[j][i];
val[v]|=val[next[v]];
}
}
}
double f(int u,int L)
{
if(L==0) return 1.0;
if(vis[u][L]) return dp[u][L];
vis[u][L]=true;
dp[u][L]=0;
for(int i=0;i<62;++i)
{
if(!val[ch[u][i]])
dp[u][L]+=p[i]*f(ch[u][i],L-1);
}
return dp[u][L];
}
char str[110];
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int t,tcase=0;
scanf("%d",&t);
while(t--)
{
tcase++;
Init();
int K;
scanf("%d",&K);
for(int i=0;i<K;++i)
{
scanf("%s",str);
insert(str);
}
scanf("%d",&n);
char c[3];
for(int i=0;i<n;++i)
{
scanf("%s",c);
scanf("%lf",&p[idx(c[0])]);
}
build();
int L;
scanf("%d",&L);
double ans=f(0,L);
printf("Case #%d: %lf\n",tcase,ans);
}
return 0;
}
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn=200+10;
const int mod=100000;
int ch[maxn][4],next[maxn],flag[maxn],size;
int indx[maxn];
void Init()
{
memset(ch[0],0,sizeof(ch[0]));
memset(next,0,sizeof(next));
indx['A']=0;indx['C']=1;indx['T']=2;indx['G']=3;
size=0;
}
void Insert(const char * s)
{
int u=0,n=strlen(s);
for(int i=0;i<n;++i)
{
int c=indx[s[i]];
if(!ch[u][c])
{
ch[u][c]=++size;
memset(ch[size],0,sizeof(ch[size]));
flag[size]=0;
}
u=ch[u][c];
}
flag[u]=1;
}
void build()
{
queue<int>q;
for(int i=0;i<4;++i)
if(ch[0][i]) q.push(ch[0][i]);
int r,u,v;
while(!q.empty())
{
r=q.front();q.pop();
for(int c=0;c<4;++c)
{
u=ch[r][c];
if(!u) {ch[r][c]=ch[next[r]][c];continue;}
q.push(u);
v=next[r];
while(v&&!ch[v][c]) v=next[v];
next[u]=ch[v][c];
flag[u]|=flag[next[u]];
}
}
}
char str[55];
ll matrix[maxn][maxn],res[maxn][maxn],tmp[maxn][maxn];
void mul(ll a[maxn][maxn],ll b[maxn][maxn])
{
for(int i=0;i<=size;++i)
for(int j=0;j<=size;++j)
{
tmp[i][j]=0;
for(int k=0;k<=size;++k)
{
tmp[i][j]+=a[i][k]*b[k][j];
tmp[i][j]%=mod;
}
}
for(int i=0;i<=size;++i)
for(int j=0;j<=size;++j)
b[i][j]=tmp[i][j];
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int m,n;
Init();
scanf("%d%d",&m,&n);
for(int i=0;i<m;++i)
{
scanf("%s",str);
Insert(str);
}
build();
memset(matrix,0,sizeof(matrix));
memset(res,0,sizeof(res));
for(int i=0;i<=size;++i)
{
if(flag[i]) continue;
for(int c=0;c<4;++c)
if(!flag[ch[i][c]])
matrix[i][ch[i][c]]++;
}
for(int i=0;i<=size;++i) res[i][i]=1;
while(n)
{
if(n&1) mul(matrix,res);
mul(matrix,matrix);
n>>=1;
}
int ans=0;
for(int i=0;i<=size;++i)
ans=(ans+res[0][i])%mod;
printf("%d\n",ans);
return 0;
}