本篇博客旨在巩固基础代码学习,不足之处还望广大大牛批评指出不胜感激
字典树目的在于可以节省大量空间存储单词或其他字符串,并且可以快速查找。
poj3630
题意:
给出若干字符串,判断某个字符串是否是其他字符串的前缀,有这样的字符串输出“NO”,否则输出“YES”。
思路:
根据字符串输的顺序不同需要考虑第一种:该字符串是否是上面输入过的字符串的前缀
第二种:该字符串是否包含之前输入的某个字符串
注意:
根据题目给定的范围可以算出字典树节点数最多有10*10000=100000,节点数少的话会wrong或RE;
输入字符串之前要getchar(),以防输入n后的回车被读入,否则会RE;
C++代码如下(数组实现字典树插入,此题还未涉及字典树查找)
#include
#include
#include
#include
#include
using namespace std;
int tot;
int s[100010][10];
int iwn[100010];
int insertt(char *a,int rt)
{
int l=strlen(a);
for(int i=0; i
#include
#include
#include
#include
using namespace std;
string s,t;
int next[100000];
int tlen=0;
int slen=0;
void getnext()
{
int i,j;
i=-1;
j=0;
next[0]=-1;
while(j>s>>t)
{
memset(next,0,sizeof(next));
getnext();
tlen=t.size();
slen=s.size();
int u=indexfind_();
if(u==-1)printf("NO:没有匹配\n");
else
printf("YES:第一次匹配的位置为:%d\n",u);
printf("匹配的次数: %d\n",count_kmp());
}
}
一道例题体会next数组神奇的应用
下图很清晰的表达出了思路,(借鉴了一个大牛的神图)
如上图,黑色线来代表字符串t,其长度是l,红色线的长度代表next[l],由next数组定义得next[l]前的字符串前缀和next[l]前的字符串的后缀及其所有子串完全相同(也就是两条线所对应的位置)。我们再求出next[l]位置处的next值,也就是图中蓝线对应的长度。同样可以得到两个蓝线对应的子串肯定完全相同,又由于第二段蓝线属于左侧红线的后缀,所以又能得到它肯定也是整个字符串的后缀。因此这道题,就是求出 l 处的next值,并一步一步的向下(递归)求出所有的next值直到next值等于零,然后倒序输出得到答案。
c++代码如下:
#include
#include
#include
#include
using namespace std;
string t;
int next[500000];
int tlen;
void getnext()
{
int i,j;
i=-1;
j=0;
next[0]=-1;
while(j>t)
{
memset(next,0,sizeof(next));
getnext();
tlen=t.size();
int k=0,ans[500000]={0};
int j=t.size();
while(j!=0)
{
ans[k++]=next[j];
j=next[j];
}
for(int i=k-2;i>=0;i--)
printf("%d ",ans[i]);
printf("%d\n",tlen);
}
}