这个算法只能求出长度
其性能分析如下
第一个图第一列是n的大小,第二列是该算法耗时ms,第二列是传统n方算法耗时ms
测试数据是小写的26个字母
思路:先保留相同的元素,记录每个元素在b里面对应的下标,在遍历a中元素,在dp数组中优先更新最小的下标,用lower_bound寻找改元素下标中大于等于dp[l+1]的下标来继续更新并把dp[l+1]下标退回,直到更新了长度或者元素的下标用完了之后就结束循环,
#include <iostream>
#include<set>
#include<stdlib.h>
#include<vector>
using namespace std;
typedef long long ll;
int main()
{
freopen("test1.out", "r", stdin);
freopen("test3.out", "w", stdout);
string a, b;
while (cin >> a >> b)
{
clock_t start, end;
start = clock();
int p = max(a.size(), b.size());
int exia[26] = { 0 }, exib[26] = { 0 };
for (auto i : a)
{
exia[i - 'a'] = 1;
}
for (auto i : b)
{
exib[i - 'a'] = 1;
}
int com[26] = { 0 };
for (int i = 0; i < 26; i++)
{
com[i] = exia[i] && exib[i];
}
string c;
for (auto i : a)
{
if (com[i - 'a'])
c += i;
}
a = c;
c = "";
for (auto i : b)
{
if (com[i - 'a'])
c += i;
}
b = c;
set<int> k[26];
int alen = a.size(), blen = b.size();
for (int i = 0; i < blen; i++)
{
k[b[i] - 'a'].insert(i);
}
vector<int> dp(alen + 1, -1);
int len = 0;
for (int i = 0; i < alen; i++)
{
int cid = a[i] - 'a';
if (k[cid].empty())
continue;
int w = 1;
auto t = k[cid].lower_bound(0);
while (!k[cid].empty() && w)
{
if (dp[len] < *t)
{
dp[++len] = *t;
k[cid].erase(t);
w = 0;
}
else
{
int l = 0, r = len, v = *t;
while (l < r)
{
int mid = (l + r + 1) >> 1;
if (dp[mid] > v)
r = mid - 1;
else
l = mid;
}
t = k[cid].lower_bound(dp[l + 1]);
k[b[dp[l + 1]] - 'a'].insert(dp[l + 1]);
dp[l + 1] = v;
if (t == k[cid].end())
w = 0;
k[cid].erase(v);
}
}
}
cout << len << '\n';
end = clock();
printf("totile time=%f\n", (float)(end - start) * 1000 / CLOCKS_PER_SEC);
}
return 0;
}