题目描述:


对于两个长度相等的字符串,我们定义其距离为对应位置不同的字符数量,同时我们认为距离越近的字符串越相似。例如,“0123”和“0000”的距离为 3,“0123”和“0213”的距离则为 2,所以与“0000”相比,“0213”和“0123”最相似。

现在给定两个字符串 S1 和 S2,其中 S2 的长度不大于 S1。请在 S1 中寻找一个与 S2 长度相同的子串,使得距离最小。

输入

输入包括多组数据。第一行是整数 T,表示有多少组测试数据。每组测试数据恰好占两行,第一行为字符串 S1,第二行为 S2。所有字符串都只包括“0”到“9”的字符。

输出

对于每组测试数据,单独输出一行“Case #c: d”。其中,c 表示测试数据的编号(从 1 开始),d 表示找到的子串的最小距离。

数据范围

1 ≤ T ≤ 100

小数据:字符串长度不超过 1000

大数据:字符串长度不超过 50000

样例输入

3
0123456789
321
010203040506070809
404
20121221
211

样例输出

Case #1: 2
Case #2: 1
Case #3: 1




解题思路:


现在假设 s1="010203040506070809",s2="404",首先对 s1 进行预处理,标记出每个字符出现的索引,得到下面的表格:

字符

出现的索引

'0'

0,2,4,6,8,10,12,14,16

'1'

1

'2'

3

'3'

5

'4'

7

'5'

9

'6'

11

'7'

13

'8'

15

'9'

17

n

ans = {0, 1, 0, 1, 0, 2, 0, 2, 0, 1, 0, 1, 0 ,1, 0, 1};

s1i…i+n 与 s20…n 中完全相同的字符的个数,最后只要统计 ans 中最大的那个,就表示距离最小。


为什么是ans[2-1],ans[4-1],ans[6-1]......这里面的i为什么要减去?个人的理解是:在S1i.......i+n中后J-i的字串中能够匹配当前字符。



下面是自己编译通过的代码:(样例数据已经通过)


#include<iostream>
#include<string>
using namespace std;

int num[10][60000],ans[60000];
int main()
{
    int T,k,len1,len2,anss;string s1,s2;
    int t=1;
    cin>>T;
    while(T>=t)
    {
        ++t;
        cin>>s1;cin>>s2;
        len1=s1.length();len2=s2.length();
        for(int i=0;i<10;++i) num[i][0]=0;
        //
        for(int i=0;i<len1;++i)
        {
            k=s1[i]-'0';
            ++num[k][0];//sum of char// k便于以后使用
            num[k][num[k][0]]=i;
            ans[i]=0;
        }
        for(int i=0;i<len2;++i)
        {
            k=s2[i]-'0';
            for(int j=1;j<=num[k][0];++j)
            {
                if(num[k][j]-i>=0) ans[num[k][j]-i]++;
            }
        }
        anss=0;
        for(int i=0;i<len1-len2+1;++i)
        {
            if(ans[i]>anss) anss=ans[i];
        }
        anss=len2-anss;//anss record the similar // anss记录的是相同字符有多少个
        cout<<"case #"<<t-1<<": "<<anss<<endl;
    }
    return 0;

}