①auto的使用
#include<set>
#include<iostream>
#include<cstdio>
#include<algorithm>
#define for0(x) for (int i = 0; i < x ; i++)
#define for1(x) for (int i = 1; i <= x ; i++)
using namespace std;
set<int>s;
int main()
{
///auto 用法1:自动判断迭代器类型
int x;
for1(10) cin>>x,s.insert(x);
for (auto i = s.begin();i != s.end(); i++ )
cout << *i << " ";
cout << endl;
///auto 用法2:对于容器可以直接方便的遍历
//string
string s;
cin >> s;
for (auto &c:s){///加上引用可以对容器内值直接修改
c++;
}
cout << s << endl;
//vector
vector<int> v;
for1(10) cin>>x,v.push_back(x);
for (auto i:v)
cout << i << " ";
cout << endl;
return 0;
}
②HDU 1867 收获
(1)如何方便输出字符串A,B去掉前几位的拼接字符串
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
char s[10000],ss[10000];
int main()
{
cin >> s >> ss;
int x,y;
cout << "第一个字符串去掉前x位,第二个去掉前y位,输入x,y" << endl;
cin >> x >> y;
printf("%s%s\n",s+x,ss+y);
return 0;
}
(2)重新梳理一下kmp的next数组构造过程
i表示以i为终点的字符串
j表示当前与这个字符串的最长匹配后缀
通过比较i和j位置的字符,判断最长后缀是否+1
如果不匹配,利用当前已匹配的部分,找出这一部分的最长公共前后缀,j跑到那个位置,这个是适配后最多的前后缀,再次
比较当前位置,如果成功,那么后缀就+1
(3)关于求A串的后缀与B串的前缀的最长相同值问题
方法一:拼接起来,最后while直到可取
方法二:
1.B串求next。
2.A串用B串来求next,这样最后i匹配完之后,j指向的就是以i结尾的串(A)和B的最长前后缀
(4)关于(3)方法二 和 主串匹配子串的区别
分别简称情况1,情况2
突然发现了情况2就是在找大串i位置为串结尾的后缀和小串的最长前缀
当j=lenm时,主串的字符肯定不等于'\0'所以此时j会回退
如果是类似剪布条,那么每次匹配完成后就让j=0,因为之前的剪掉了,现在相当于重新开始
③exkmp的板子+自己摸索的时候的三张图
const int maxn=100010; //字符串长度最大值
int next[maxn],ex[maxn]; //ex数组即为extend数组
//预处理计算next数组
void GETNEXT(char *str)///求子串KMP
{
int i=0,j,po,len=strlen(str);
next[0]=len;///初始化next[0],为什么初始化为len
while(str[i]==str[i+1]&&i+1<len) i++;///计算next[1]
next[1]=i;
///为什么暴力匹配next[1],因为next[0] = len,前缀和后缀重合,没有意义
///简单来说,就是这么搞会错
po=1;//初始化po的位置
for(i=2;i<len;i++)
{
///疑问:j<0的情况不包含在第一种情况中吗
///也就是保证相等的部分在当前位置的前面
///哪些情况会进入第一种?P延伸的距离很短且没有到,那么此时直接等于这个肯定不对,证明这种情况没有进情况1
///当前问题:对第一种第二种的具体界定?
/// 第一种情况:已知相同(并非匹配)部分 前移(与PO位置有关)所在位置next(也就是定义的len)小于相同长度,那么就等于len
/// j<0表示当前没有相同段,不管你要和那个next比,最小就是0,
///也就是 (>=0的数) >= 0,进入else
if(next[i-po]+i<next[po]+po)//第一种情况,可以直接得到next[i]的值
next[i]=next[i-po];
else//第二种情况,要继续匹配才能得到next[i]的值
{ /// P = PO + next[PO] -1,表示保证相同的一部分的最远距离
j=next[po]+po-i;/// 等价于 P -i + 1,也就是相同部分的长度
if(j<0)j=0;///如果i>po+next[po],则要从头开始匹配,应该挺常见的情况
while(i+j<len&&str[j]==str[j+i])///计算next[i],从第一个条件退出循环表示后缀都匹配完了,把这个条件放前面否则可能下标越界
j++;
next[i]=j;
po=i;//更新po的位置
}
}
}
//计算extend数组
void EXKMP(char *s1,char *s2)///这个部分根据kmp匹配的原理,就是在以小串做前缀对照,来求大串的对应最长后缀
{ ///唯一不同,这里暴力求ex[0],没有之前那个前后缀重合的烦恼
int i=0,j,po,len=strlen(s1),l2=strlen(s2);
GETNEXT(s2);//计算子串的next数组
while(s1[i]==s2[i]&&i<l2&&i<len)//计算ex[0]
i++;
ex[0]=i;
po=0;//初始化po的位置
for(i=1;i<len;i++)
{
if(next[i-po]+i<ex[po]+po)//第一种情况,直接可以得到ex[i]的值
ex[i]=next[i-po];
else//第二种情况,要继续匹配才能得到ex[i]的值
{
j=ex[po]+po-i;
if(j<0)j=0;//如果i>ex[po]+po则要从头开始匹配
while(i+j<len&&j<l2&&s1[j+i]==s2[j])//计算ex[i]
j++;
ex[i]=j;
po=i;//更新po的位置
}
}
}
求next数组,进入if的情况举例,以及为什么不用继续匹配直接得到结果
求Ex数组
j<0的情况