zoukankan      html  css  js  c++  java
  • HDOJ(1238) KMP

    Substrings

    http://acm.hdu.edu.cn/showproblem.php?pid=1238

    先找到长度最短的字符串,把它的子串和该子串的逆序(按长度从大到小)依次与其他字符串匹配。

    如果某个子串或它的逆序(如:“ro” ,”or“)和其他字符串都匹配,就返回此时的长度。

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<vector>
    #include<algorithm>
    using namespace std;
    
    //下标以0开始的KMP
    void get_next(string b, int *next)
    {
        int i=0;
        int j=-1;
        next[i]=-1;
        int len_b=b.size();
        while(i<len_b-1)
        {
            if(j==-1||b[i]==b[j])
            {
                ++i;
                ++j;
                if(b[i]!=b[j])
                    next[i]=j;
                else
                    next[i]=next[j];
            }
            else
            {
                j = next[j];
            }
        }
    }
    
    int KMP(string a,string b)
    {
        int i=0;
        int j=0;
        int len_a=a.size();
        int len_b=b.size();
        int next[101];
        get_next(b,next);
        while(i<len_a&&j<len_b)
        {
            if(j==-1||a[i]==b[j])
            {
                ++i;
                ++j;
            }
            else
            {
                j=next[j];
            }
        }
        if(j>=len_b)
            return 1;
        else
            return 0;
    }
    
    int solve(vector<string> str,int mini)
    {
        string sub1,sub2;
        int i,j,k,m,res=0;
        int len=str[mini].size();
        for(i=len;i>=1;i--)
        {
            for(j=0;i+j<=len;j++)
            {
                sub1=str[mini].substr(j,i);  //选取str[mini]中以j开头长度为i的字串
                sub2=sub1;
                reverse(sub2.begin(),sub2.end());//逆置字符串
                int l=str.size();
                for(k=0;k<l;k++)
                {
                    string s=str[k];
                    if(KMP(s,sub1)==0&&KMP(s,sub2)==0)
                    {
                        break;
                    }
                }
                if(k>=l)
                {
                    
                    res=i;
                    goto A;
                }
            }
        }
        A: return res;
    }
    int main()
    {
        int t,n,i,mini;
        vector<string> str;
        string s;
        scanf("%d",&t);
        while(t--)
        {
            str.clear();
            scanf("%d",&n);
            for(i=0;i<n;i++)
            {
                cin>>s;
                str.push_back(s);
            }
            mini=0;
            int len=str.size();
            for(i=1;i<len;i++)
            {
                if(str[i].size()<str[mini].size())
                {
                    mini=i;
                }
            }
            printf("%d
    ",solve(str,mini));
        }
        return 0;
    }
    View Code

    KMP模板

    下标以0开始

    void get_next(string b, int *next)
    {
        int i=0;
        int j=-1;
        next[i]=-1;
        int len_b=b.size();
        while(i<len_b-1)
        {
            if(j==-1||b[i]==b[j])
            {
                ++i;
                ++j;
                if(b[i]!=b[j])
                    next[i]=j;
                else
                    next[i]=next[j];
            }
            else
            {
                j = next[j];
            }
        }
    }
    
    int KMP(string a,string b)
    {
        int i=0;
        int j=0;
        int len_a=a.size();
        int len_b=b.size();
        int next[101];
        get_next(b,next);
        while(i<len_a&&j<len_b)
        {
            if(j==-1||a[i]==b[j])
            {
                ++i;
                ++j;
            }
            else
            {
                j=next[j];
            }
        }
        if(j>=len_b)
            return i-len_b;
        else
            return 0;
    }
    View Code

    下标从1开始

    void get_next(char *b,int *next)
    {
        int i=1;
        int j=0; 
        next[1]= 0; 
        int len_b=strlen(b)-1;     //下标从1开始,子串的长度=strlen(b)-1
        while(i<len_b) 
        { 
            if(j==0||b[i]==b[j])   //b[i]表示后缀的单个字符
            {                      //b[j]表示前缀的单个字符
                ++i; 
                ++j; 
                if (b[i]!=b[j]) 
                    next[i]=j; 
                else 
                    next[i]=next[j]; 
            }  
            else   
                j=next[j];        //若字符不相同,则j值回溯
        } 
    }
    int KMP(char *a,char *b,int pos)
    {
        int i=pos;               //i用于主串a当前位置下标值
                                 //若pos不为1,则从pos开始
        int j=1;                 //j用于字串b当前位置下标值
        int len_a=strlen(a)-1; 
        int len_b=strlen(b)-1;
        int next[101];
         get_next(b,next);        //对字串b分析,得到next数组
        while(i<=len_a&&j<=len_b)
        {
            if(j==0||a[i]==b[j])
            {
                ++i;
                ++j;
            }
            else
            {
                j=next[j];
            }
        }
        if(j>len_b)
            return i-len_b;   
        else
            return 0;
    }
    View Code

    下标以1开始的next数组,实际上,是下标以0开始的next数组的值+1。KMP算法最重要的是得到子串的next[]。

  • 相关阅读:
    nullnullConnecting with WiFi Direct 与WiFi直接连接
    nullnullUsing WiFi Direct for Service Discovery 直接使用WiFi服务发现
    nullnullSetting Up the Loader 设置装载机
    nullnullDefining and Launching the Query 定义和启动查询
    nullnullHandling the Results 处理结果
    装置输出喷泉装置(贪心问题)
    数据状态什么是事务?
    停止方法iOS CGD 任务开始与结束
    盘文件云存储——金山快盘
    函数标识符解决jQuery与其他库冲突的方法
  • 原文地址:https://www.cnblogs.com/chiry/p/3269707.html
Copyright © 2011-2022 走看看