题目描述
Given sequence ss of length nn and sequence tt of length mm, find the length of the longest common subsequence of ssand tt.
输入描述:
There are multiple test cases. The first line of input contains an integer TT(1≤T≤1031≤T≤103), the number of test cases. For each test case: The only line contains 77 integers, nn, mm, pp, xx, aa, bb, cc (1≤n1≤n, m≤106m≤106, 0≤x0≤x, aa, bb, c<p≤109c<p≤109). nn is the length of ss, mm is the length of tt. To avoid large input, you should generate the sequences as follows: For each i=1i=1, 22, ⋯⋯, nn in order, update xx to (ax2+bx+c) mod p(ax2+bx+c)modp, and then set sisi to xx. And then, for each i=1i=1, 22, ⋯⋯, mm in order, update xx to (ax2+bx+c) mod p(ax2+bx+c)modp, and then set titi to xx. It is guaranteed that the sum of nn and the sum of mm over all test cases does not exceed 106106.
输出描述:
For each test case: Output an integer -- the length of the longest common subsequence of ss and tt, in one line.
示例1
输入
2 4 3 1024 1 1 1 1 3 4 1024 0 0 0 0
输出
0 3
说明
In the first sample, s=[3,13,183,905]s=[3,13,183,905] and t=[731,565,303]t=[731,565,303]. In the second sample, s=[0,0,0]s=[0,0,0] and t=[0,0,0,0]t=[0,0,0,0].
题意: 给出一个长度为n的数组以及一个长度为m的数组,求它们的最长公共子序列,数组中的值按照一定规则生成,给出x、a、b和c,令x = a*x^2 + b*x + c,然后把x填入数组中第i个位置,如此往复直至遍历完数组。
分析: 由于n和m都是1e6级别的,所以没法直接跑n^2的lcs算法,可以注意到两个数组中数据生成都是有规律的,第i+1个位置的值是通过第i个位置的值得到的,如果一旦出现a[i]等于b[j],那么a数组第i个位置和b数组第j个位置后面的值一定是相同的,所以问题就很好解决了,只需要记录下a数组中a[i]首次出现的位置,然后遍历b数组,当b[i]在a数组中出现过时,就可以更新一次答案,最终结果取最大值。
具体代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <string>
#include <unordered_map>
using namespace std;
unordered_map<int, int> mp;
signed main()
{
int T;
cin >> T;
while(T--){
mp.clear();
int n, m, p, x, a, b, c;
scanf("%d%d%d%d%d%d%d", &n, &m, &p, &x, &a, &b, &c);
for(int i = 1; i <= n; i++){
x = ((1ll*a*x%p*x%p+1ll*b*x%p)%p+c)%p;
if(!mp.count(x))
mp[x] = i;
}
int ans = 0;
for(int i = 1; i <= m; i++){
x = ((1ll*a*x%p*x%p+1ll*b*x%p)%p+c)%p;
if(mp[x]) ans = max(ans, min(n-mp[x]+1, m-i+1));
}
printf("%d\n", ans);
}
return 0;
}