package primary_class;
public class Test{
//用动态规划来代替KMP算法,str1中是否含有str2,并且返回起始下标
public static int search(String str1,String str2){
if(str1==null||str1.length()<1||str2==null||str2.length()<1){
return 0;
}
int m=str1.length();
int n=str2.length();
int[][] dp=new int[n][256];//n值表示的是状态的数目,也就是str2的长度,256表示的即将状态转换时当前遇到的字符,256是字符ASCII码的范围
dp[0][str2.charAt(0)]=1;//表示当前状态是0,即还没有开始匹配,若遇到的字符是str2的第一个字符一样的字符,那么状态就会切换为1状态,否则状态保持在状态0
int j=0;//当前的状态序号
int x=0;//进行状态转移(或者说是状态回退)时的状态序号
//dp数组只与str2有关,for循环求出dp[][]数组
for(j=1;j<n;j++){//j值从状态1开始循环,前面初始条件已经考虑了状态0的情况
for(int c=0;c<256;c++){
dp[j][c]=dp[x][c];//这里先写出一般情况,若当前遇到的字符是任意字符c,那么状态转移到x状态,x状态是与j状态具有共同最长前缀的位置
}
dp[j][str2.charAt(j)]=j+1;//特殊情况也是最顺利的情况,若当前遇到的字符是与str2自身当前状态的字符一致的字符,那么就可以直接状态前移,不需要状态回退。即数组值也就是下一个状态就是j+1
x=dp[x][str2.charAt(j)];//此外,还需要更新转移状态(辅助状态)的值,因为这个值在判断匹配的过程中也是变动的。更新x的思路与下面for循环中更新j状态值是一样的。假设当前状态 j 只有遇到 字符"C" 才能前移状态,变成j+1,若遇到除了"C"以外的字符,状态 j 会把这个字符委托给状态 X 处理,也就是 dp[j][其他字符] = dp[x][其他字符]:
}
//str2匹配str1的过程,利用到dp[][]
j=0;//j值要重新初始化,开始匹配str1
for(int k=0;k<m;k++){
j=dp[j][str1.charAt(k)];//这一句会改变j值,改变j状态的思路与上面改变辅助状态x的思路是一致的
if(j==n){//当状态到达了str2的末尾,则说明匹配结束,并且匹配成功
return k-n+1;//返回str2在str1中的起始下标
}
}
return -1;//str2不在str1中
}
public static void main(String[] args){
String str1="absscdsdsd";
String str2="sd";
System.out.print(search(str1,str2));
}
}
用动态规划来代替KMP算法
最新推荐文章于 2023-04-16 18:17:37 发布