今天我看了一下KMP算法,神奇的是我知道它每个字在讲什么,但是写了一个题怎么都过不了。
讲讲我看到的 数据结构KMP算法配图详解(超详细)_哈顿之光的博客-CSDN博客_数据结构kmp算法详解
KMP算法的作用是在一个已知字符串中查找子串的位置,也叫做串的模式匹配
朴素的模式匹配:从主串s 和子串t 的第一个字符开始,将两字符串的字符一一比对,如果出现某个字符不匹配,主串回溯到第二个字符,子串回溯到第一个字符再进行一一比对。如果出现某个字符不匹配,主串回溯到第三个字符,子串回溯到第一个字符再进行一一比对…一直到子串字符全部匹配成功。(这种方法是在查找字串的时候一下就想到的,但是效率太低,最坏的情况下时间复杂度为O(m*n))
我之前不理解的地方:不知道怎么看,现在知道原来如此
一个字符串最长相等前缀和后缀。
构造next数组关键的地方:每一个字符前的字符串都有最长相等前后缀,而且最长相等前后缀的长度是我们移位的关键,用一个next数组存储子串的最长相等前后缀的长度
下次比较的地方就是不匹配的字符前的字符串 最长相等前后缀的长度。
也是不匹配的字符处的next数组next[5]应该保存的值,也是子串回溯后应该对应的字符的下标
next数组作用有两个:
①next[i]的值表示下标为i的字符前的字符串最长相等前后缀的长度。
②next[i]的值表示下标为i的字符前的字符串最长相等前后缀的长度。
并查集
并查集详解 ——图文解说,简单易懂(转)_多反思,多回顾,要坚持。-CSDN博客_并查集详解
刷了3个题:
题一:P3367 【模板】并查集 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
模板题:主要是合并,合并在一个根节点之下,判断是不是一个集合,只要知道它们的根节点是不是一样就好了。
#include<stdio.h>
int pre[10010];
int find(int x)
{
if(pre[x]==x)//如果x的父节点是它自己,那么就是根节点
return x;
return pre[x]=find(pre[x]);//递归的方法查找根节点,回溯时改变当前节点的父节点,直接指向根节点
}
/*
int Find_Set2(int x)
{
int y = x;
while(y!= -1)
y = father[y];
return y;
}
*/
int main()
{
int n,m,z,x,y;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
pre[i]=i;//它的上级是它自己
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&z,&x,&y);
if(z==1) //合并操作
{
pre[find(y)]=find(x);
}
else
{
//查询操作,判断它两的根节点是否相等
if(find(x)==find(y))
printf("Y\n");
else
printf("N\n");
}
}
}
题二:P1551 亲戚 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
和上面这个题基本上一样,就不解释了
#include<stdio.h>
int pre[10010];
int find(int x)
{
if(pre[x]==x)//如果x的父节点是它自己,那么就是根节点
return x;
return pre[x]=find(pre[x]);//递归的方法查找根节点,回溯时改变当前节点的父节点,直接指向根节点
}
/*
int Find_Set2(int x)
{
int y = x;
while(y!= -1)
y = father[y];
return y;
}
*/
int main()
{
int n,m,p,m1,m2;
scanf("%d%d%d",&n,&m,&p);
for(int i=1;i<=n;i++)
pre[i]=i;//它的上级是它自己
for(int i=0;i<m;i++)
{
scanf("%d%d",&m1,&m2);
pre[find(m2)]=find(m1);//连接子集(将m2的根节点的父节点变成m1的根节点
}
for(int i=0;i<p;i++)
{
scanf("%d%d",&m1,&m2);
//查询操作 ,如果两个根节点说一样的证明在一棵树上,是亲戚关系
if(find(m1)==find(m2))
printf("Yes\n");
else
printf("No\n");
}
}
题三:P1827 [USACO3.4]美国血统 American Heritage - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
没过。。。。。
明天还是刷题。