У меня есть интересное решение O (N) времени и пространства O (M) для этой задачи.
N - длина текста, а M - длина шаблона, который необходимо найти.Я объясню вам алгоритм, потому что я реализую его на C ++.
. Предположим, что введенный вами ввод соответствует 3141592653, а последовательность паттернов, число которых нужно найти, - 123.Я начну с хэш-карты, которая отображает символы на их позиции в шаблоне ввода.Я также беру массив размера M, изначально инициализированный равным 0.
string txt,pat;
cin >> txt >> pat;
int n = txt.size(),m = pat.size();
int arr[m];
map<char,int> mp;
map<char,int> ::iterator it;
f(i,0,m)
{
mp[pat[i]] = i;
arr[i] = 0;
}
Я начинаю искать элементы сзади и проверяю, есть ли каждый элемент в шаблоне или нет.Если этот элемент находится в шаблоне.Я должен что-то сделать.
Теперь, когда я начинаю смотреть со спины, если я нахожу 2 и предыдущий, я не нашел никаких 3.Это 2 не имеет значения для нас. Потому что любой 1, найденный после того, как он сформирует такую последовательность 12 и 123, не будет сформирован Ryt?считать.Также в текущем положении я нашел 2, и он будет формировать последовательности 123 только с 3, найденными ранее, и сформирует x последовательностей, если мы нашли x 3 ранее (если будет найдена часть последовательности до 2).Таким образом, полный алгоритм заключается в том, что всякий раз, когда я нахожу элемент, который присутствует в массиве, я проверяю его позицию j, соответственно, в которой он присутствовал в шаблоне (хранится в хэш-карте).Я просто инкрементно увеличиваю
arr[j] += arr[j+1];
, означая, что он будет вносить вклад в последовательности из 3, найденных до того, как это будет сделано?и если j найдено m-1, я просто увеличу его
arr[j] += 1;
Проверьте приведенные ниже фрагменты кода, которые делают это
for(int i = (n-1);i > -1;i--)
{
char ch = txt[i];
if(mp.find(ch) != mp.end())
{
int j = mp[ch];
if(j == (m-1))
arr[j]++;
else if(j < (m-1))
arr[j] += arr[j+1];
else
{;}
}
}
Теперь рассмотрим факт
каждыйindex i в массиве хранит количество раз, которое подстрока шаблона S [i, (m-1)] применяется в качестве последовательности входной строки. Итак, в конце выведите значение arr [0]
cout << arr[0] << endl;
Код с выводом (уникальные символы в шаблоне) http://ideone.com/UWaJQF
Код с выводом (допускаются повторения символов) http://ideone.com/14DZh7
Расширение работает, только если в шаблоне есть уникальные элементы Что если шаблон имеетуникальные элементы, тогда сложность может переместиться в O (MN). Решение похоже без использования DP, только когда элемент, встречающийся в образце, появился, мы просто увеличили соответствующую ему позицию массива j, теперь мы должны обновить вхождения всех этих символов в образце,привести к сложности O (N * максимальная частота charater)
#define f(i,x,y) for(long long i = (x);i < (y);++i)
int main()
{
long long T;
cin >> T;
while(T--)
{
string txt,pat;
cin >> txt >> pat;
long long n = txt.size(),m = pat.size();
long long arr[m];
map<char,vector<long long> > mp;
map<char,vector<long long> > ::iterator it;
f(i,0,m)
{
mp[pat[i]].push_back(i);
arr[i] = 0;
}
for(long long i = (n-1);i > -1;i--)
{
char ch = txt[i];
if(mp.find(ch) != mp.end())
{
f(k,0,mp[ch].size())
{
long long j = mp[ch][k];
if(j == (m-1))
arr[j]++;
else if(j < (m-1))
arr[j] += arr[j+1];
else
{;}
}
}
}
cout <<arr[0] << endl;
}
}
может быть расширен аналогичным образом без DP в строках с повторениями, но затем завершенxity будет больше O (MN)