USC oj 1404: Search(搜索)

USC oj 1404: Search

  1. Description

When we search for something on internet, we always use two wildcard characters “” and “?”. ”” represents 0 or more lowercase letters,”?” represents 1 lowercase letter。

We would use the two wildcard characters, while we are not sure about the keywords. Suppose that many records are stored in our database, each of them consists of lowercase letters. Give you a keyword, could you tell me how many records match with the keyword?
For example: the keyword is “jym*y?”,then “jiyanmoyu”,”jyanmoyu”,”jymyu” are all match with it.

  1. Input

Test cases less than 20. The first line of each test case is the keyword, the second line is an integer n, represents n records stored in database (1<=n<=10000). The length of each record is not more than 50.

  1. Output

For each line in the input, there should be one line of output contains an integer representing the number of the records matching with keyword.

  1. Sample Input

jiyanmoyu
2
jiyanmoyu
huyanluanyu
ji*moy?
3
jiyanmoyu
jimoyu
huyanluanyu

  1. Sample Output

1
2

题目链接:
http://cs203.net:9988/problem.php?id=1404


本人的思路是用递归,设计了一个函数,函数的两个参数为当前要比较的字符的位置(前面的已经匹配好)。
假设j,k,为当前要比较的字符的位置,判断对应字符是否相等,如果相等,j与k都加1,如果不相等,判断j位置的字符,如果是?则k++,如果不是?也不是 * 则停止比较,这个不匹配。
重点是 * 的时候如何做,因为 * 会忽略0到n个字符,所以就先用忽略0个字符尝试,将要比较的(k,j)传给函数,继续进行下一轮的比较,如果最终判断不匹配,则返回0,用(k+1,j)尝试…用(k+2,j)尝试…用(k+3,j)尝试,直到k+n大于当前储存字符串的长度,

     看了一下标程,上面给的是dp,估计我那个也是伪dp思想吧。。。。
 这里贴一下dp思路,有兴趣的可以再看看
 
 f[i][j]表示p的前i个字符串,与s的前j个字符串是否匹配 
 p为匹配串,s为带匹配串
 如果p[i] 为* ,那么 f[i][j] = f[i-1][j]  |  f[i][j-1]);
 即:f[i][j-1]成功匹配的话,*可匹配s[j-1],或者f[i-1][j]
 匹配成功的话,*不匹配任何字符;
 如果p[i]为?,那么 f[i][j] = f[i-1][j-1];
 其他   f[i][j] = f[i-1][j-1] & (p[i-1] == s[j-1])

给一组特殊数据吧

星星??星?星星星?
6
a
ab
abc
abcd
abcde
abcdef


#include<bits/stdc++.h>
using namespace std;
char a [55],ori[65];
int asi,orisi,count1;
int judge(int k,int n);
int main()
{
    while(scanf("%s",ori)!=EOF)
    {
        int n;
        count1=0;
        scanf("%d",&n);
        for(int i=0; i<n; i++)
        {
            scanf("%s",a);
            asi=strlen(a);
            orisi=strlen(ori);
            if(judge(0,0)) count1++;
        }
        printf("%d\n",count1);
    }
    return 0;
}

int judge(int k,int j)//当前要比较的字符串的位置
{
    int fu=0;// * 覆盖字符的多少
    while(k<asi&&j<orisi)
    {
        if(ori[j]==a[k])  k++;
        else
        {
            if(ori[j]=='*')
            {
                while(ori[j]=='*'&&j<orisi) j++;//如果后面都是*肯定成立
                    if(j==orisi) return 1;
                while(1)
                {
                    if(judge(k+fu,j)) return 1;//判断 * 覆盖fu个字符能否成立
                    if(k+fu==asi) return 0;
                    fu++;
                }
            }
            else if(ori[j]=='?')  k++;
            else break;
        }
        j++;
    }
    if(k==asi&&j==orisi) return 1;//到最后如果匹配计数器一定能推到最后一个字符
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值