拿到这道题 显然第一反应是写暴力
初始思路:找到每个串的公共串 然后再求公共串的PIN码可能性
显然不可做 主要是找公共串过于繁琐
然后逆向思考
因为PIN码只有10000种
所以可以考虑枚举PIN码再验证其是否可行
对于一个动作序列 我们记录它的下一个k(1 <= k <= 9)在哪一位
这样验证一个PIN码时只需按PIN码跳下去(如图)
1 for(int i = 1; i <= n; i++){ 2 int x; char p[10005]; scanf("%d%s", &x, p); 3 for(int j = 0; j <= 9; j++) last[j] = -1; 4 while(x--){ 5 for(int j = 0; j <= 9; j++) next[j][x + 1] = last[j]; 6 last[p[x] - '0'] = x + 1; 7 } 8 for(int j = 0; j <= 9; j++) next[j][0] = last[j]; 9 for(int j = 0; j <= 9999; j++) 10 flag[j] |= check(j); 11 }
若PIN码未读完跳到-1 则PIN码不可行
1 bool check(int x){ 2 int last = -1, now; 3 for(int k = 1, i = 0; k <= 4; k++){ 4 now = x % 10; x /= 10; 5 if(last == now) continue ; 6 i = next[now][i]; last = now; 7 if(i == -1) return 1; 8 } 9 return 0; 10 }
时间复杂度 : O(∑t∗10+10000∗n)