//BF算法
/*对于此算法,也是最常规的做法,同时遍历主串和模式串,判断字符相等则同时向后继续判断是否匹配
当不匹配时,主串从刚才开始的位置的下一个位置开始向后继续判断,而模式串则从最开始位置,
同此时的主串一起同时向后判断遍历判断,重复此过程
对于一定量的效率可行
当数据量达到一定量时,会花费很长很长时间取等待结果
*/
#include<bits/stdc++.h>
#define N 1001
using namespace std;
int Index(char s[],char t[])
{
int s1=strlen(s);
int t1=strlen(t);
int i=0,j=0;
while(i<s1&&j<t1){
if(s[i]==t[j]){//继续匹配下一个字符
i++;
j++;
}
else{//主串,子串指针回溯重新开始下一次匹配
i=i-j+1;//主串从下一个位置开始匹配
j=0;//子串从头开始匹配
}
}
if(j>=t1){
return (i-t1);//返回匹配的第一个字符的下标
}
else{
return -1;//匹配不成功
}
}
int main()
{
char a[N];
cout<<"请输入主串:";
gets(a);
char b[N];
cout<<"请输入模式串:";
gets(b);
int t=Index(a,b);
cout<<t<<endl;
return 0;
}
//KMP算法
/*KMP由三位大牛的名字命名,这个算法可以将算法的效率大大提高!对于大数据的效率远高于前面的算法!
此算法的思想是:没必要去每次重新判断子串,也莫必要去每次拉回主串
对于模式串,通过计算模式串的前缀和后缀相等的个数,来确定每次应该从模式串的那个位置去判断对应的主串的元素
用一个next数组来存储这些信息,next数组遵循一个固定的规律:next数组第一个元素总是-1(其值可以为0,但为了统一操作),
其余元素则为前缀与后缀数相等的个数-1;
以此规律来匹配主串与模式串,通过对应的next数组值来更改下标,达到减少匹配次数。
从而大大减少时间。
*/
#include<bits/stdc++.h>
#define NotFound -1
void BuildNext(char *pattern,int *next)
{
int i,j;
int m=strlen(pattern);
next[0]=-1;//对于next数组,第一个元素没有与其相等的前缀,所以为-1,(可以为0,为了统一操作,取-1)
for(j=1;j<m;j++){
i=next[j-1];//i表示前缀和后缀相等的字符个数-1,即下次匹配可以直接定位到模式串的下标
while((i>=0)&&(pattern[i+1]!=pattern[j])){//前面有匹配的,但当前前缀与后缀不匹配
i=next[i];//i往回缩
}
if(pattern[i+1]==pattern[j]){//前缀和后缀匹配
next[j]=i+1;//将当前i+1赋值给next数组
}
else{//前缀后缀不匹配
next[j]=-1;
}
}
}
int KMP(char *string,char *pattern)
{
int n=strlen(string);
int m=strlen(pattern);
int s,p,*next;
if(n<m){//模式串比主串长,直接返回,模式匹配失败
return NotFound;
}
next=(int *)malloc(m*sizeof(int));//next数组分配单元
BuildNext(pattern,next);//得到next数组
s=p=0;
while(s<n&&p<m){
if(string[s]==pattern[p]){//字符匹配,指针同时后移,继续匹配
s++;
p++;
}
else if(p>0){//将模式串指针拉回到可以跳过匹配的字符下标,+1是为了和next数组统一
p=next[p-1]+1;
}
else{//第一个字符都不匹配,主串继续向后遍历匹配
s++;
}
}
return p==m?(s-m):NotFound;//跳出循环s和p相等,表示找到了,s-m即为初始位置下标
}
int main()
{
char string[]="aaaaaa bbbbaaabbbccc";
char pattern[]="aaabbb";
int p=KMP(string,pattern);
if(p==NotFound){
printf("Not Found!");
}
else{//输出第一次出现的子串下标及剩余字符
printf("%d %s\n",p,string+p);
}
return 0;
}
#include<bits/stdc++.h>
#define N 1001
using namespace std;
void GetNext(char t[],int next[])
{
int j,k;
j=0;
k=-1;
next[0]=-1;//第一个无前缀匹配,为-1
while(j<(strlen(t)-1)){
if(k==-1||t[j]==t[k]){//k==-1或者匹配成功继续向下匹配
j++;
k++;
next[j]=k;
}
else{
k=next[k];
}
}
}
int KMPIndex(char s[],char t[])
{
int next[N]={0};
GetNext(t,next);
int s1=strlen(s);
int t1=strlen(t);
int i=0;
int j=0;
while(i<s1&&j<t1){
if(j==-1||s[i]==t[j]){//j=-1,j++使得j又重新指向模式串第一个元素
i++;//匹配,继续匹配下面的元素
j++;
}
else{
j=next[j];//i不变,j后退
}
}
if(j>=t1){
return (i-t1);
}
else{
return -1;
}
}
int main()
{
char a[N];
cout<<"请输入主串:";
gets(a);
char b[N];
cout<<"请输入模式串:";
gets(b);
int t=KMPIndex(a,b);
cout<<t<<endl;
return 0;
}
package KMP;
import java.util.Arrays;
import java.util.Scanner;
public class KMP {
public static int[] prefix(String pattern){//获得模式串前后缀匹配字符串的长度
//并存入数组中
int len = pattern.length();//获取模式串的长度
int[] result = new int[len];//创建和模式串等长的存取匹配长度的数组
result[0] = 0;//result的第一个元素无匹配的值,所以其匹配长度肯定为0
int p = 0;//标志模式串匹配的长度
int i = 1;//从1开始遍历剩下的字符并判断
while (i<len){
if (pattern.charAt(i) == pattern.charAt(p)){//相等的情况
p++;//匹配长度+1
result[i] = p;//赋给数组对应位置
i++;//继续向后判断
}else{//不相等的情况
if (p>0) {//没到第一个位置,预防越界
p = result[p - 1];//p等于匹配长度数组的前一个位置,即侧着移位
}else{//不相等且到了第一个位置
result[i] = p;//赋0
i++;//继续向后判断
}
}
}
return result;
}
public static void change(int[] nums){
for (int i = nums.length-1; i >0; i--) {//将所有匹配长度前移,形成统一
nums[i] = nums[i-1];
}
//给nums[0]赋值
nums[0] = -1;
}
public static void kmpSearch(String nums,String pattern){
int[] array1 = prefix(pattern);//array1为统计前后缀匹配长度的数组
change(array1);
int i = 0;
int j = 0;
while(i<nums.length()){
if (j==pattern.length()-1&&nums.charAt(i)==pattern.charAt(j)){//说明匹配完了,成功
System.out.println("在主串中下标为:"+(i-pattern.length()+1)+"的位置定位到了模式串");
//匹配完成后,继续向后匹配
j = array1[j];
}
if (nums.charAt(i)==pattern.charAt(j)){//相等同时挪动
i++;
j++;
}else{//不相等
j = array1[j];//将j移到其对应的已匹配的地方,从此位置继续匹配
if (j == -1){//说明没有匹配的,将主串和模式串的指针都移动
i++;
j++;
}
}
}
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("请输入主串:");
String nums = in.next();
System.out.print("请输入模式串:");
String pattern = in.next();
kmpSearch(nums,pattern);
}
}