2019年7月1日 随便写的一些东西

①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的情况

猜你喜欢

转载自blog.csdn.net/weixin_43768644/article/details/94412147