给定两个字符串str和match,长度分别为N和M。实现一个算法,如果字符串str中含有子串match,则返回match在str中的开始位置,不含有则返回-1
若出现了多次,则按照升序输出所有出现位置
[要求]
时间复杂度为
第一行一个字符串str
第二行一个字符串match
输出若干个数,分别为match在str中出现的位置,从0开始标号。
若不存在输出-1
acbc bc
2
acbc bcc
-1
ababab ab
0 2 4
保证字符集为小写字母
#include<bits/stdc++.h>
using namespace std;
int main()
{
string str,match;
getline(cin,str);
getline(cin,match);
bool f=false;
for(int i=0;i<str.size()-match.size();i++)
{
string s=str.substr(i,match.size());
if(s==match)
{
cout<<i<<" ";
f=true;
}
}
if(!f)
cout<<-1;
return 0;
} import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
char[] str1 = br.readLine().toCharArray();
char[] str2 = br.readLine().toCharArray();
if(str1.length < str2.length){
System.out.println(-1);
}else{
StringBuilder sb = new StringBuilder();
int[] next = getNextArr(str2);
int i1 = 0, i2 = 0;
int find = kmp(str1, str2, i1, i2, next);
while(find > -1){
sb.append(find + " ");
i1 = find + 1; // i1不断后移,与str2匹配
find = kmp(str1, str2, i1, i2, next);
}
System.out.println(sb.length() == 0? -1: sb.toString().trim());
}
}
private static int kmp(char[] str1, char[] str2, int i1, int i2, int[] next) {
if(i1 + str2.length >= str1.length) return -1;
while(i1 < str1.length && i2 < str2.length){
if(str1[i1] == str2[i2]){ // 字符相等,两个字符都移动
i1 ++;
i2 ++;
}else if(next[i2] > -1){
i2 = next[i2]; // 不相等且还能往前跳,则i2往前面跳
}else{
i1 ++; // str2已经跳到0了还没法匹配成功,就只能移动str1的指针了
}
}
return i2 == str2.length? i1 - i2: -1;
}
private static int[] getNextArr(char[] str) {
if(str.length == 1) return new int[]{-1};
int[] next = new int[str.length];
next[0] = -1;
int i = 2, prev = 0;
while(i < str.length){
if(str[i - 1] == str[prev]){
next[i] = prev + 1; // 最长与后缀相等的前缀长度+1
prev ++;
i ++;
}else if(prev > 0){
prev = next[prev]; // 不相等就往前跳
}else{
next[i] = prev;
i ++;
}
}
return next;
}
} #include <iostream>
#include<string>
#include<vector>
using namespace std;
int main() {
string s1,s2;
cin>>s1>>s2;
int n=s2.size();
vector<int> next(n);
next[0]=0;
int j=0;
for(int i=1;i<n;i++)
{
while(j>0&&s2[i]!=s2[j])
j=next[j-1];
if(s2[i]==s2[j])
j++;
next[i]=j;
}
j=0;
vector<int> ans;
for(int i=0;i<s1.size();i++)
{
while(j>0&&s1[i]!=s2[j])
j=next[j-1];
if(s1[i]==s2[j])
j++;
if(j==n)
{
ans.emplace_back(i-n+1);
}
}
if(ans.empty())
ans.emplace_back(-1);
for(int num: ans)
cout<<num<<" ";
}
// 64 位输出请用 printf("%lld") import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String str = in.nextLine();
String match = in.nextLine();
int[] next = getNextArray(match);
int i = 0, j = 0;
boolean flag=false;
while (i < str.length()) {
if (str.charAt(i) == match.charAt(j)) {
i++;
j++;
} else if (j == 0) {
i++;
} else {
j = next[j];
}
if (j == match.length()) {
System.out.print((i - j) + " ");
j = next[j];
flag=true;
}
}
if(!flag) System.out.print(-1);
}
public static int[] getNextArray(String match) {
int n = match.length();
if (n == 1) return new int[] {-1, 0};
int[] next = new int[n + 1];
next[0] = -1;
next[1] = 0;
int cnt = 0;
int i = 2;
while (i <= n) {
if (match.charAt(i - 1) == match.charAt(cnt)) {
next[i++] = ++cnt;
} else if (cnt == 0) {
next[i++] = 0;
} else {
cnt = next[cnt];
}
}
return next;
}
} #include "bits/stdc++.h"
using namespace std;
int main()
{
string T,P;
cin>>T>>P;
int len1=T.size();
int len2=P.size();
if(len1<len2){cout<<-1;return 0;}
//求next数组
vector<int> next(len2,0);
next[0]=-1;
int t=-1;
int j=0;
while(j<len2-1)
{
if(t<0||P[j]==P[t])
{
j++;t++;
next[j]=P[j]!=P[t]?t:next[t];
}
else
{
t=next[t];
}
}
int i=0;
j=0;
bool flag=0;
while(i<len1&&j<len2)
{
if(j<0||T[i]==P[j]){i++;j++;}
else {j=next[j];}
//如果找到了一个匹配的,就右移一位继续寻找
if(j==len2){flag=1;cout<<i-j<<" ";i=i-j+1;j=0;}
}
if(flag==0)cout<<-1;
return 0;
} #include<iostream>
#include<vector>
using namespace std;
vector<int> getNext(string pattern){
int k = -1; //匹配的前缀长度,-1代表长度为0
vector<int> next(pattern.length(), -1);
for(int i = 1; i < pattern.length(); i++){
while(k > -1 && pattern[k + 1] != pattern[i]){
k = next[k];
}
if(pattern[k + 1] == pattern[i]){
k = k + 1;
}
next[i] = k;
}
return next;
}
vector<int> KMP(string str, string pattern){
vector<int> next = getNext(pattern);
int k = -1;
vector<int> res;
for(int i = 0; i < str.length(); i++){
while(k > -1 && pattern[k + 1] != str[i]){
k = next[k];
}
if(pattern[k + 1] == str[i]){
k = k + 1;
}
if(k == pattern.length() - 1){
res.push_back(i - pattern.length() + 1);
k = -1;
}
}
return res;
}
int main(){
string str, pattern;
cin >> str >> pattern;
vector<int> res = KMP(str, pattern);
if(res.empty()){
cout << -1 << endl;
}else{
for(int i = 0; i < res.size(); i++){
cout << res[i] << " ";
}
}
}
// 比较好的短的KMP
#include<iostream>
#include<string>
#include<vector>
using namespace std;
class Solution{
public:
vector<int> getpatternLen(string str,string match){
//1.生成b数组
//cout<<str<<endl;
//cout<<match<<endl;
vector<int> b(match.size() + 1);
int j = -1;
int i = 0;
b[i] = j;
while(i < match.size()){
while(j>=0 && match[i] != match[j])
j = b[j];
i++;
j++;
b[i] = j;
}
j = 0;//str
i = 0;//pattern
int index = 0;
vector<int> res;
while(j < str.size()){
while(i>=0 && str[j] != match[i])
i = b[i];//跳转到该跳转的位置
i++;
j++;
if(i == match.size()){
res.push_back(j - match.size());
if(j < str.size())
i = 0;
else
break;
}
}
if(res.empty()){
res.push_back(-1);
}
return res;
}
};
int main(){
string str;
string match;
getline(cin,str);
getline(cin,match);
vector<int> res;
Solution c1;
res = c1.getpatternLen(str,match);
for(int i=0;i<res.size();i++){
cout<<res[i]<<" ";
}
return 0;
} #include<cstdio>
(802)#include<cstring>
int main(){
char str[500010];
char str1[500010];
while(scanf("%s",str)!=EOF){
scanf("%s",str1);
int len1=strlen(str);
int len2=strlen(str1);
int flag=0;
for(int i=0;i<=len1-len2;++i){
int k=0;
if(str[i]==str1[k]){
int j=i;
while(str[j]==str1[k]&&str[j]!='\0'){
j++;
k++;
}
if(k==len2){
if(flag==0)
{
printf("%d",i);
flag=1;
}else{
printf(" %d",i);
}
}
}
}
if(flag==0){
printf("-1");
}
}
return 0;
} #KMP算法
import java.util.*;
import java.io.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
String match = sc.nextLine();
KMP k = new KMP();
List<Integer> result = k.kmp(str,match);
//return result;
for(int i : result){
System.out.print(i);
System.out.print(" ");
}
}
}
class KMP{
public List<Integer> kmp(String str,String match){
char[] matches = match.toCharArray();
char[] strs = str.toCharArray();
int[] next = getNext(matches);
List<Integer> result = new ArrayList<>();
int curmatch = 0;
int index = 0;
while(index<strs.length){
while(curmatch != -1 && strs[index] != matches[curmatch]){
curmatch = next[curmatch];
}
curmatch++;
if(curmatch == matches.length){
result.add(index-matches.length+1);
curmatch = next[curmatch-1];
}else
index++;
}
if(result.isEmpty())
result.add(-1);
return result;
}
private int[] getNext(char[] chars){
int[] next = new int[chars.length];
next[0] = -1;
for(int i = 1;i<chars.length;i++){
int k = i-1;
while(k != 0 && chars[i-1] != chars[next[k]]){
k = next[k];
}
next[i] = next[k]+1;
}
return next;
}
} #include <iostream>
#include <string>
#include <vector>
using namespace std;
vector<int> getNext(const string& match) {
vector<int> ret(match.length());
ret[0] = -1;
if(match.length() == 1)
return ret;
ret[1] = 0;
int cn = ret[2-1];
for(int i = 2; i < ret.size();) {
if(match[i-1] == match[cn])
ret[i++] = ++cn;
else if(cn > 0)
cn = ret[cn];
else
ret[i++] = 0;
}
return ret;
}
vector<int> KMP(const string& str, const string& match) {
vector<int> ret;
if(str.length() < match.length())
return ret;
vector<int> next = getNext(match);
int i = 0;
int j = 0;
while(i < str.length()) {
while(i < str.length() && j < match.length()) {
if(str[i] == match[j]) {
i++;
j++;
}
else if(next[j] == -1) {
i++;
}
else {
j = next[j];
}
}
if(j == match.length()) {
ret.push_back(i-j);
i = i-j+1; // 重点
j = 0;
}
}
return ret;
}
int main() {
string str;
cin >> str;
string match;
cin >> match;
vector<int> ret = KMP(str, match);
if(ret.empty())
cout << -1 << endl;
else {
for(auto& e : ret)
cout << e << " ";
cout << endl;
}
return 0;
} #include <iostream>
#include <vector>
#include <string>
using namespace std;
// 暴力匹配算法
int ViolentMatch(string s, string p) {
int i = 0, j = 0, slen = s.size(), plen = p.size();
while (i < slen && j < plen)
{
if (s[i] == p[j]){
i++;
j++;
}
else{
i = i - j + 1;
j = 0;
}
}
if (j == plen) return i - j;
else return -1;
}
// KMP算法
int KMP(string s, string p, vector<int>next) {
int i = 0, j = 0, slen = s.size(), plen = p.size();
while (i < slen && j < plen)
{
if (j == -1 || s[i] == p[j]){
i++;
j++;
}
else{
j = next[j];
}
}
if (j == plen) return i - j;
else return -1;
}
// MultiKMP算法
vector<int> MultiKMP(string s, string p, vector<int>next) {
vector<int> res;
int i = 0, j = 0, slen = s.size(), plen = p.size();
while (i < slen)
{
if (j == -1 || s[i] == p[j]){
i++;
j++;
}
else{
j = next[j];
}
if (j == plen){
res.push_back(i - j);
j = 0;
}
}
return res;
}
vector<int> GetNext(string p)
{
vector<int> next(p.size());
next[0] = -1;
int k = -1, j = 0;
while (j < p.size() - 1)
{
//p[k]表示前缀,p[j]表示后缀
if (k == -1 || p[j] == p[k]){
++k;
++j;
if (p[j] != p[k]) next[j] = k;
else next[j] = next[k];
}
else{
k = next[k];
}
}
return next;
}
int main(){
string s1, s2;
cin >> s1 >> s2;
vector<int> next = GetNext(s2);
// 暴力匹配第一次出现位置
//cout << ViolentMatch(s1, s2) << endl;
// KMP匹配第一次出现位置
//cout << KMP(s1, s2, next) << endl;
// KMP匹配无重复所有出现位置
vector<int> res = MultiKMP(s1, s2, next);
if (!res.empty()){
for (int i = 0; i < res.size(); i++){
cout << res[i] << ' ';
}
cout << endl;
}
else{
cout << -1 << endl;
}
return 0;
}