1字符串匹配问题
在一篇英文文章中查找指定人名,人名使用26个字母(可以是大写也可是小写),空格及两个通配符(*或?),通配符*表示零个或多个任意字母,通配符?表示一个任意字母,如J*Smi??可以匹配John Smith.
分析:从开始到结尾,到第n+1个字符是否匹配成功取决于到第n个字符是否匹配成功和第n+1个字符能否匹配,也就是收益只取决于当前的状态和下一个决策量,满足无后效性,因此可用动态规划算法。
(1)用矩阵dp来描述匹配的状态,纵轴代表含有通配符的字符串S2,横轴代表要匹配的字符串S1,dp[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)收益表示(递推式)
情况一: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));
}
}
情况二S1与S2都含有通配符
若S1或S2当前为*: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])