hdu - 3925 - Substring(枚举匹配)

来源:互联网 发布:php银联支付流程 编辑:程序博客网 时间:2024/05/19 18:40

题意:给两个整数a、b,问a最少加上多少后,b成为a的子串。( 0 <= a <= 10^100, 0 <= b <= 10^7)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3925

——>>开始用C++<string>库中的find来找子串,结果TLE了,后来,枚举匹配位:

13464164643467464646   1836,

             | | | |                   | | | |

             | | | |                  1836

            1836

使4646变成1836,那么需要+ (11836 - 4646);(1836不够大,在前面补1,后面补0,这个数据刚刚好是最后一个位置,不用补0)

使1646变成1836,那么需要+ (18360000000000 -164643467464646 );(1836够大,后面补0就行)

但是上面的运算都是用字符串来运算的,而不是直接用 + - ;

从4开始,一直枚举到最左边的1;

WA,WA,WA……多少次,太痛苦了……

最后,发现我的程序测试几个40多位的a,7位的b都是正确的,有点意思了,再测,测,测……终于发现:当a长度比b的长度小时,没做处理,修改——>AC!

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 100 + 10;bool cmp(char *s, int high, int low, char *sub)     //判断s[high]~s[low]是否就是字符串sub{    int j = 0;    for(int i = high; i <= low; i++) if(s[i] != sub[j++]) return 0;    return 1;}int cmpp(char *a, char *b)      //字符数组表示的a与b的大小比较{    int len_a = strlen(a), len_b = strlen(b), len = min(len_a, len_b), i;    if(len_a != len_b)      //在程序除去了前导0,这里可直接比较位数来确定谁大谁小    {        if(len_a > len_b) return 1;        else return -1;    }    else        //位数相等时    {        for(i = 0; i < len; i++)        {            if(a[i] > b[i]) return 1;       //数a > b            if(a[i] < b[i]) return -1;      //数a < b        }        return 0;       //如果上面没返回,那么a == b    }}int to_int(char *s, int high, int low)      //将字符数组s转换成整数{    int ret = 0;    for(int i = high; i <= low; i++) ret = ret*10 + s[i]-'0';    return ret;}int main(){    int i, j, k, u, v, cnt = 1, T;    char a[maxn], b[maxn], B[maxn], c[maxn], minn[maxn];        //a, b为输入数组,B, c为过程中处理的中间数组,minn存最小值(结果)    scanf("%d", &T);    while(T--)    {        scanf("%s%s", a, b);        int len_a = strlen(a), len_b = strlen(b);        for(i = 0; i < maxn; i++) minn[i] = '9';        //初始化为最大        for(i = len_b; i < maxn; i++) b[i] = '0'; b[maxn-1] = 0;        //为b后面赋0,下面减法用到        int bb = to_int(b, 0, len_b-1);     //求b的值        if(len_a < len_b)       //当子串长度比原串更长时,子串更大        {            int aa = to_int(a, 0, len_a-1);            printf("Case #%d: %d\n", cnt++, bb-aa);            continue;        }        bool ok = 0;        //匹配成功标志        for(i = len_a-len_b; i >= 0; i--)       //从后往前一一模拟        {            int aa = to_int(a, i, i+len_b-1);            if(aa == bb)        //剪枝,匹配成功时            {                ok = 1;                break;            }            else        //匹配不成功时            {                for(u = 0; u < maxn; u++) B[u] = b[u];      //取一个b到B,不能直接操作原数组!                for(j = len_a-1, k = len_a-1-i; j >= i; j--, k--)                {                    if(B[k] >= a[j]) c[k] = B[k] - a[j] + '0';                    else        //借位                    {                        if(k-1 >= 0) B[k-1]--;                        c[k] = B[k] + 10 - a[j] + '0';                    }                }                c[len_a-i] = 0;     //设结束字符                for(v = 0; v < len_a-i; v++) if(c[v] != '0') break;     //除去前导0                if(v != 0) for(u = 0; v <= len_a-i; u++,v++) c[u] = c[v];                if(cmpp(c, minn) < 0) for(u = 0; u <= len_a-i; u++) minn[u] = c[u];     //更新            }        }        if(ok) printf("Case #%d: %d\n", cnt++, 0);        else        //还要1次对“-1”位的模拟        {            for(u = 0; u < maxn; u++) B[u] = b[u];      //取一个b到B,不能直接操作原数组!            for(j = len_a-1, k = len_a; j >= 0; j--, k--)            {                if(B[k] >= a[j]) c[k] = B[k] - a[j] + '0';                else        //借位                {                    B[k-1]--;                    c[k] = B[k] + 10 - a[j] + '0';                }            }            c[0] = B[0];        //存下第1位            c[len_a+1] = 0;     //设结束字符            for(v = 0; v < len_a+1; v++) if(c[v] != '0') break;     //除去前导0            if(v != 0) for(u = 0; v <= len_a+1; u++,v++) c[u] = c[v];            if(cmpp(c, minn) == -1) for(u = 0; u <= len_a+1; u++) minn[u] = c[u];       //更新            printf("Case #%d: %s\n", cnt++, minn);        }    }    return 0;}