HDU 2087 HDU 1867 KMP标准模板题

贴两道题,其中HDU2087是中文题,故不解释题目,

思路是,一发KMP,但是特别处理最后一位的失配边为0,这样就可以保证“判断完成但是不多判断”。

第二题,很毒瘤的题,要求求出,给定字符串A,B能够缠到一起组成的子字符串长度“长度较小且字典序较小”的一个。。。。要求,假设str1+str2组成答案,则str1的后缀和str2的前缀中相同的部分,只出现一次。。于是做法就是,两法KMP,特判答案咯。。。然而。。。。此题。。最有难度的地方是读懂提。。。。看了别人的提解读懂得。。。。

 

 

2087AC代码:

#include<bits/stdc++.h>
using namespace std;

const long long MAXN=1233;
long long f[MAXN];
char str1[MAXN];
long long len1;
char str2[MAXN];
long long len2;

bool init()
{
    cin>>str1;
    if(str1[0]=='#')return false;
    cin>>str2;
    len1=strlen(str1);
    len2=strlen(str2);
    f[0]=0;
    f[1]=0;
    for(int i=1;i<len2;++i)
    {
        int j=f[i];
        while(j&&str2[i]!=str2[j])j=f[j];
        f[i+1]= str2[i]==str2[j]? j+1:0;
    }f[len2]=0;
    return 1;
}

int main()
{
    while(init())
    {
        long long summ=0;
        int j=f[0];
        for(int i=0;i<=len1;++i)
        {
            if(j==len2)summ++;
            while(j&&str1[i]!=str2[j])j=f[j];
            j= str1[i]==str2[j]? j+1:0;
        }cout<<summ<<"\n";
    }
    
}

 

1867AC代码:

#include<bits/stdc++.h>
using namespace std;
const long long MAXN=100233;
class str
{
    public:
        int f[MAXN];
        char s[MAXN];
        int len;
};
str s1,s2;
string ans1,ans2;
void init()
{
    s1.f[0]=0;s1.f[1]=0;
    s2.f[0]=0;s2.f[1]=0;
    ans1.clear();
    ans2.clear();
    s1.len=strlen(s1.s);
    s2.len=strlen(s2.s);
    for(int i=1;i<s1.len;++i)
    {
        int j=s1.f[i];
        while(j&&s1.s[i]!=s1.s[j])j=s1.f[j];
        s1.f[i+1]= s1.s[i]==s1.s[j] ? j+1:0;
    }
    for(int i=1;i<s2.len;++i)
    {
        int j=s2.f[i];
        while(j&&s2.s[i]!=s2.s[j])j=s2.f[j];
        s2.f[i+1]= s2.s[i]==s2.s[j] ? j+1:0;
    }
}

bool com(string &str1,string &str2)
{
    int len=min(str1.length(),str2.length());
    for(int i=0;i<len;++i)
    {
        if(str1[i]!=str2[i])
        {
            if(str1[i]<str2[i])break;
            else return false;
        }
    }
    return 1;
}
int main()
{
    cin.sync_with_stdio(false);
    while(cin>>s1.s>>s2.s)
    {
        init();
        int j=0;
        for(int i=0;i<s1.len;++i)
        {
            ans1.push_back(s1.s[i]);
            while(j&&s1.s[i]!=s2.s[j])j=s2.f[j];
            j= s1.s[i]==s2.s[j]? j+1:0;
        }
        for(;j<s2.len;++j)
        {
            ans1.push_back(s2.s[j]);
        }
        j=0;
        for(int i=0;i<s2.len;++i)
        {
            ans2.push_back(s2.s[i]);
            while(j&&s2.s[i]!=s1.s[j])j=s1.f[j];
            j= s2.s[i]==s1.s[j]? j+1:0;
        }
        for(;j<s1.len;++j)
        {
            ans2.push_back(s1.s[j]);
        }
        if(ans1<=ans2&&ans1.length()<=ans2.length())
        {
            cout<<ans1<<"\n";
        }else cout<<ans2<<"\n";
    }
    return 0;
}

 

posted @ 2017-08-23 16:13  六花的邪王真眼  阅读(186)  评论(0编辑  收藏  举报