計算重複

計算重複ios


這道題咱們先考慮樸素算法:算法

首先,咱們從\(s_1\)串的第一位開始,枚舉\(s_2\)每一位的對應位置,最後記錄最終能夠到達的位置,用每一位均如此,模擬便可。優化

該算法不夠好。spa


考慮優化:咱們設\(f[i,j]\)\(s_1[i]\)打頭最少須要多少個字符串才能拼出\(2_{j}\)\(s_2\)字符串來。code

\(f[i,0]\)暴力預處理。ci

\[f[i,j]=f[i,j-1]+f[(i+f[i,j-1])modulo(s1.size),j-1] \]

最後在二進制拼湊時,沒必要枚舉每一位,由於第一位已經包含全部了。字符串

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
using namespace std;
const int SIZE = 100 + 5;
string s1, s2;
int n1, n2;
long long f[SIZE][32];
int main()
{
	while(cin >> s2 >> n2 >> s1 >> n1)
	{
		memset(f, 0, sizeof(f));
		bool fail = false;
		for(int i = 0; i < s1.size(); ++ i)
		{
			int k = i;
			for(int j = 0; j < s2.size(); ++ j)
			{
				int cnt = 0;
				while(s1[k % s1.size()] != s2[j])
				{
					++ k, ++ cnt;
					if(cnt >= s1.size())
					{
						fail = true;
						break;
					}
				}
				k = (k + 1) % s1.size();
				++ cnt;
				f[i][0] += cnt;
				if(fail) break;
			}
			if(fail) break;
		}
		if(fail)
		{
			puts("0");
			continue;
		}
		for(int j = 1; j <= 30; ++ j)
		{
			for(int i = 0; i < s1.size(); ++ i)
			{
				f[i][j] = f[i][j - 1] + f[(i + f[i][j - 1]) % s1.size()][j - 1];
			}
		}
		long long m = 0, pos = 0;
		for(int i = 30; i >= 0; -- i)
		{
			if(pos + f[pos % s1.size()][i] <= s1.size() * n1)
			{
				pos += f[pos % s1.size()][i];
				m += 1 << i;
			}
		}
		printf("%d\n", m / n2);
	}
	return 0;
}
相關文章
相關標籤/搜索