经典算法设计:动态规划(2)字符串匹配

1字符串匹配问题

      在一篇英文文章中查找指定人名,人名使用26个字母(可以是大写也可是小写),空格及两个通配符(*或?),通配符*表示零个或多个任意字母,通配符?表示一个任意字母,如J*Smi??可以匹配John Smith.

分析:从开始到结尾,到第n+1个字符是否匹配成功取决于到第n个字符是否匹配成功和第n+1个字符能否匹配,也就是收益只取决于当前的状态和下一个决策量,满足无后效性,因此可用动态规划算法。

(1)用矩阵dp来描述匹配的状态,纵轴代表含有通配符的字符串S2,横轴代表要匹配的字符串S1dp[i][j]表示s2的前i个字符能与S1的前j个字符匹配情况,若为true则表示匹配成功,否则匹配失败。

(2)设置初值,增加一行一列表示初值,dp[0][0]=ture,dp[0][i](i>0)表示S1还未被匹配,因此dp[0][i]=false(i>0);d[i][0]=d[i-1][0]&&S[i]==*’)

当终止状态为true时表示匹配成功,为false表示匹配失败

(3)收益表示(递推式)

                                                                      《经典算法设计:动态规划(2)字符串匹配》

       情况一:S1含有通配符,S2不含有通配符

       若S2当前为*dp[i][j]=dp[i-1][j]||dp[i][j-1]

       若S2当前为非*dp[i][j]=dp[i-1][j-1]&&(S2[i]==S1[j]||S2[i]==’?’)

java代码如下:

import java.io.*;
class strMatching
{
	private static boolean strMatching(String s1,String s2)
	{
		boolean[][] dp=new boolean[s1.length()+1][s2.length()+1];
		dp[0][0]=true;
		for(int i=1;i<=s2.length();i++)
			dp[0][i]=false;
		for(int i=1;i<=s1.length();i++)
		{
			char s1_char=s1.charAt(i-1);
			dp[i][0]=dp[i-1][0]&&(s1_char=='*');
		    for(int j=1;j<=s2.length();j++)
			{
				if(s1.charAt(i-1)=='*')
					dp[i][j]=dp[i-1][j]||dp[i][j-1];
				else
				{
					dp[i][j]=dp[i-1][j-1]&&(s1.charAt(i-1)==s2.charAt(j-1)||s1.charAt(i-1)=='?');
				}
			}
        }	
    return dp[s1.length()][s2.length()];		
	}
	public static void main(String[] args)
	{
		String s1="a*c",s2="abc";
		System.out.println(strMatching(s1,s2));
	}
}

      情况二S1S2都含有通配符

      若S1S2当前为*dp[i][j]=dp[i-1][j]||dp[i][j-1]

      否则:dp[i][j]=dp[i-1][j-1]&&(S1[i]==’?’||S2[j]==’?’||S1[j]||S2[i]==S1[j])

 

    原文作者:动态规划
    原文地址: https://blog.csdn.net/gds2014/article/details/50437628
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞