19-字符串匹配(kmp || substr,find)

。_饼干妹妹 提交于 2020-03-29 02:57:33

链接:https://www.nowcoder.com/acm/contest/77/C
来源:牛客网

时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

有一个字符串 让你找到这个字符串 S 里面的子串T 这个子串 T 必须满足即使这个串的前缀 也是这个
串的后缀 并且 在字符串中也出现过一次的(提示 要求满足前后缀的同时也要在字符串中出现一次 只是前后缀可不行 输出最长满足要求字符串)

输入描述:

给出一个字符串 长度 1 到 1e6  全部是小写字母

输出描述:

如果找的到就输出这个子串T 如果不行就输出 Just a legend
示例1

输入

fixprefixsuffix

输出

fix
示例2

输入

abcdabc

输出

Just a legend方法一:kmp:注意枚举的模式串,以及原串与给定字符之间的差别:
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
string str, mo;
int Next[1000005];

void getNext(){
	Next[0] = -1;  //一定要初始化 
	int i = 0, j = -1, len = mo.length();
	while(i < len){
		if(j == -1 || mo[i] == mo[j])  //j表示前i-1个字符中前缀和后缀相等的长度 
			Next[++i] = ++j;		   //如果跳转的值相同,则Next的下一位对应的为前一位加一	
		else 
			j = Next[j];   //j回溯 
	}
}

int kmp(){
	int ans = 0;
	int i = 0, j = 0, l1 = str.length(), l2 = mo.length();
	while(i < l1){
		if(j == -1 || str[i] == mo[j]) 
			i++, j++;
		else
			j = Next[j];    //只需回溯j 
		if(j == l2)			//在原串中找到一个模式串 
			ans++;
	}
	return ans;
}
 
int main(){
	ios::sync_with_stdio(false);  //取消cin 与 scanf()同步,刚刚没加超时了 
	string tt;
	cin >> tt;
	int len = tt.length(), flag = 1;
	for(int i = len - 2, j; i >= 1; i--){  //枚举所以可能的前缀长度,注意不是范围不是0~len/2,要保证中间子串不用前缀后缀重合即可 
		string s;
		for(j = 0; j < i; j++){     //判断是否与后缀相等 
			if(tt[j] != tt[len - i + j]){
				break;
			}
			s += tt[j];
		}
		if(j == i){
			mo = s;			//将前缀作为模式串 
			getNext();
		//	str = tt;
			for(int k = 1; k < len - 1; k++) //中间不与前缀后缀重合的子串作为原串,注意范围!!! 
				str += tt[k];
			int ct = kmp();
			if(ct >= 1){          	 //在原串中找到即可 
				cout << s << endl;
				flag = 0;
				break;
			}
			str.clear();
		}
	}
	if(flag){
		cout << "Just a legend" << endl;
	}
	return 0;
}
/*
aaaaa
结果:
aaa 
*/

  

  第二次写:

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int Next[1000005];

void getNext(string p){
  int j = 0, k = -1, len = p.length();
  Next[0] = -1;
  while(j < len){
    if(k == -1 || p[j] == p[k]){
    /*
		Next[++j] = ++k; //换成下面的if和else 
	
	*/	
      if(p[++j] == p[++k]){
        Next[j] = Next[k];
      }
      else{
        Next[j] = k;
      }
    }
    else{
      k = Next[k];
    }
  }
}

int main()
{
  string str, p, pp;
  cin >> str;
  int len = str.length();
  int ct = 0, k = 1;

  while(k < len - 1){
    p = str.substr(0, k);
    pp = str.substr(len - k, k);
    if(p != pp){
      k++;
      continue;
    }
    getNext(p);
    int count = 0, i = 0, j = 0;
    while(i < len){
      if(j == -1 || str[i] == p[j]){
   		j++, i++;
      }
      else{
        j = Next[j];
      }
      if(j == k){
        count++;
        j = 0; i = i - k + 1; 
        if(count >= 3){
          ct = k;
          break;
        }
      }
    }
    k++;
  }
  if(ct == 0){
    cout << "Just a legend" << endl;
  }
  else{
    cout << str.substr(0, ct) << endl;
  }
    return 0;
}

  

 

方法二:用substr,find:

  

#include<iostream>
#include<cstring>
#include <string>
using namespace std;
string s;

int main(){
    cin >> s;
    int k = 1, l = s.size();
    string ans = "";
    while (l>2 && k<l){
        string ss = s.substr(0, k);//拷贝s第0个数开始,长度为k
        if (s.substr(l - k, k) == ss)
        {
            string sss = s.substr(1, l - 2);
            ///cout << sss.find(ss) << endl;
            if (sss.find(ss)<l - 2)
                ans = ss;
        }
        k++;
    }
    if (ans == "")
        cout << "Just a legend" << endl;
    else
        cout << ans << endl;
}

  


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!