Problem:
D: しりとり圧縮 (Shiritori Compression)
問題
えびちゃんとかにちゃんの二人はしりとりをしました。えびちゃんはしりとりで出た単語のメモを見ています。
えびちゃんは、この単語列
w_1
,
w_2
,
...
,
w_N
から冗長な連続部分列を、存在しなくなるまで取り除きたいと思っています。えびちゃんの思う冗長な連続部分列とは以下のように定義されます。
以下を満たす
i
,
j
が存在したとき、連続部分列
w_i
,
...
,
w_{j-1}
は冗長です。
i < j
なる添字
i
,
j
について、単語
w_i
と
w_j
の先頭の文字が等しい。
このとき、えびちゃんは添字
i
以上
j-1
以下の単語を取り除きます。
たとえば、次のような単語列を考えます。
apple→editor→random→me→edge
これは、次のように圧縮されます。
apple→edge
editor と edge の先頭の文字が e で一致しているため、editor から edge の直前（me）までの単語が取り除かれます。
えびちゃんの判断基準では、末尾の文字が同じであっても冗長とは見なさないことに注意してください。たとえば、上の圧縮済み単語列において、apple と edge の末尾の文字はどちらも e ですが、このことによって単語が取り除かれることはありません。
また、以下のような例も考えられます。
orange→eel→luck
banana→at→tomb→bus→sound→does→some
peach→hero→owl→loop→proof→fish→he
これらはそれぞれ次のように圧縮できます。いずれも、最後の単語は保存されることに注意してください。
orange→eel→luck
すでに圧縮済みです。
bus→some
banana から bus、sound から some がそれぞれ圧縮可能です。
peach→he
proof→fish→he と圧縮することもできますが、圧縮後の単語数が異なっていることに注意してください。
えびちゃんのメモが与えられるので、それらを圧縮して得られる単語列の長さ（単語数）の最小値
L
を出力してください。
なお、「同じ単語が複数回現れる」または「ある単語の先頭の文字が直前の単語の末尾の文字と一致していない」ことは起こらないと仮定して構いません。
入力形式
N
w_1
...
w_N
一行目に単語数
N
が与えられ、
1+i
行目には
i
番目の単語が与えられます。
制約
1\leq N\leq 10^5
1\leq
$\sum_{i=1}^N$
|w_i| \leq 10^6
w_i
の各文字は英小文字
出力形式
L
を一行に出力してください。それ以外の余計な文字は含まれてはいけません。
入力例1
7
banana
at
tomb
bus
sound
does
some
出力例1
2
上で挙げた例です。
入力例2
7
peach
hero
owl
loop
proof
fish
he
出力例2
2
上で挙げた別の例です。

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;

int N;
int dp1[200009][27];
int dp2[200009][27];
int Letter[200009];
string S[200009];

int main() {
    // Step 1. Input
    cin >> N;
    for (int i = 1; i <= N; i++) cin >> S[i];
    for (int i = 1; i <= N; i++) Letter[i] = S[i][0] - 'a';
    Letter[N + 1] = 26;

    // Step 2. Dynamic Programming
    for (int i = 0; i <= N; i++) {
        for (int j = 0; j < 27; j++) dp1[i][j] = (1 << 30);
        for (int j = 0; j < 27; j++) dp2[i][j] = (1 << 30);
    }
    dp1[0][Letter[1]] = 0;
    dp2[0][Letter[1]] = 0;
    for (int i = 1; i <= N; i++) {
        int idx = Letter[i + 1];
        dp1[i][idx] = min(dp1[i][idx], dp2[i - 1][Letter[i]] + 1);
        for (int j = 0; j < 27; j++) dp1[i][idx] = min(dp1[i][idx], dp1[i - 1][j] + 1);
        for (int j = 0; j < 27; j++) dp2[i][j] = min(dp1[i][j], dp2[i - 1][j]);
    }

    // Step 3. Output
    cout << dp1[N][Letter[N + 1]] << endl;
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 34504
final_rank: 18

code_snippet: #include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
const int INF = (int)1e9 + 7;
template<class T> inline bool chmin(T &a, T b) { return a > b ? (a = b, 1) : 0; }

vector<vector<int>> calc_next(const string &s) {
    int n = s.size();
    vector<vector<int>> nxt(n + 1, vector<int>(26, n));
    for (int i = n - 1; i >= 0; i--) {
        for (int j = 0; j < 26; j++) nxt[i][j] = nxt[i + 1][j];
        nxt[i][s[i] - 'a'] = i;
    }
    return nxt;
}

int main() {
    int n; cin >> n;
    string cat;
    for (int i = 0; i < n; i++) {
        string s; cin >> s;
        cat += s.front();
    }
    auto nxt = calc_next(cat);
    vector<int> dp(n + 1, INF);
    dp[0] = 1;
    for (int i = 0; i < n; i++) {
        chmin(dp[i + 1], dp[i] + 1);
        chmin(dp[nxt[i + 1][cat[i] - 'a']], dp[i]);
    }
    cout << dp[n - 1] << endl;
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 16680
final_rank: 16

code_snippet: #include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
const int INF = (int)1e9 + 7;
template<class T> inline bool chmin(T &a, T b) { return a > b ? (a = b, 1) : 0; }

vector<vector<int>> calc_next(const string &s) {
    int n = s.size();
    vector<vector<int>> nxt(n + 1, vector<int>(26, n));
    for (int i = n - 1; i >= 0; i--) {
        for (int j = 0; j < 26; j++) nxt[i][j] = nxt[i + 1][j];
        nxt[i][s[i] - 'a'] = i;
    }
    return nxt;
}

int main() {
    int n; cin >> n;
    string cat;
    for (int i = 0; i < n; i++) {
        string s; cin >> s;
        cat += s.front();
    }
    auto nxt = calc_next(cat);
    vector<int> dp(n + 1, INF);
    dp[0] = 1;
    for (int i = 0; i < n; i++) {
        chmin(dp[i + 1], dp[i] + 1);
        int ne = nxt[i + 1][cat[i] - 'a'];
        if (ne == n) continue;
        chmin(dp[ne], dp[i]);
    }
    cout << dp[n - 1] << endl;
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 16632
final_rank: 15

code_snippet: #include "iostream"
#include "climits"
#include "list"
#include "queue"
#include "stack"
#include "set"
#include "functional"
#include "algorithm"
#include "string"
#include "map"
#include "unordered_map"
#include "unordered_set"
#include "iomanip"
#include "cmath"
#include "random"
#include "bitset"
#include "cstdio"
#include "numeric"
#include "cassert"
#include "functional"
#include "ctime"

using namespace std;

constexpr long long int MOD = 1000000007;
//constexpr int MOD = 1000000007;
//constexpr int MOD = 998244353;
//constexpr long long int MOD = 998244353;
constexpr double EPS = 1e-8;

//int N, M, K, H, W, L, R;
long long int N, M, K, H, W, L, R;


int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);

	cin >> N;
	vector<string>s(N);
	for (auto &i : s)cin >> i;
	vector<int>dis(N,MOD);
	map<char, set<int>>mp;
	for (int i = 0; i < N; i++) {
		mp[s[i][0]].insert(i);
	}
	dis[0] = 1;
	deque<int>Q;
	Q.push_back(0);
	while (!Q.empty()) {
		int cn = Q.front();
		Q.pop_front();
		auto it = mp[s[cn][0]].upper_bound(cn);
		if (it != mp[s[cn][0]].end()) {
			if (dis[*it] > dis[cn]) {
				dis[*it] = dis[cn];
				Q.push_front(*it);
			}
		}
		if (cn + 1 < N) {
			if (dis[cn + 1] > dis[cn] + 1) {
				dis[cn + 1] = dis[cn] + 1;
				Q.push_back(cn + 1);
			}
		}
	}
	cout << dis.back() << endl;
}
accuracy: 1
time_ms: 30
memory_kb: 13700
final_rank: 10

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;


signed main(){
    ios::sync_with_stdio(false);
	cin.tie(0);
    cout << fixed << setprecision(20);

    int n;
    cin>>n;
    vector<vector<int>> v(26);
    string s[n];
    for(int i=0;i<n;i++){
        cin>>s[i];
        v[s[i][0]-'a'].push_back(i);
    }
    int dp[n+1];
    int INF = 1e9;
    for(int i=0;i<=n;i++) dp[i] = INF;
    int now[26]={};
    dp[0] = 0;
    for(int i=0;i<n;i++){
        dp[i+1] = dp[i]+1;
        int t = s[i][0]-'a';
        if(now[t]){
            int p = v[t][now[t]-1];
            dp[i+1] = min(dp[i+1], dp[p+1]);
        }
        now[t]++;

    }
    cout << dp[n] << endl;

}
accuracy: 1
time_ms: 10
memory_kb: 9216
final_rank: 4

code_snippet: #include<iostream>
#include<vector>
#include<algorithm>
#include<utility>
#include<string>
#include<cmath>
#include<cstring>
#include<queue>
#include<map>
#include<climits>
#include<set>


using namespace std;
typedef pair<int, int> pii;
typedef long long int ll;
typedef pair<ll, ll> pll;
int dx[4] = { 1,0,0,-1 };
int dy[4] = { 0,1,-1,0 };

#define ARRAY_MAX 100005 

const int INF = 1e9 + 7;
const int MOD = 1e9 + 7;

int dp[ARRAY_MAX];
int wmin[ARRAY_MAX];

int main() {

	int n;
	cin >> n;
	vector<string> s(n);

	for (int i = 0; i < n; i++)
	{
		cin >> s[i];
	}

	memset(dp, INF, sizeof(dp));
	memset(wmin, INF, sizeof(wmin));

	dp[0] = 0;

	for (int i = 0; i < n; i++)
	{
		dp[i + 1] = min(dp[i] + 1,wmin[s[i][0]-'a']);
		wmin[s[i][0]-'a'] = dp[i + 1];
	}
	cout << dp[n] << endl;

}
accuracy: 1
time_ms: 40
memory_kb: 10004
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;
const int IINF = INT_MAX;
const int MAX_N = int(1e5 + 5);

int main() {
    int n, dp[MAX_N];
    vector<int> pos[26];
    string w[MAX_N];
    cin >> n;
    for(int i=0;i<n;i++){
        cin >> w[i];
        pos[w[i][0]-'a'].push_back(i);
    }
    for(int i=0;i<26;i++){
        pos[i].push_back(IINF);
    }
    fill(dp,dp+n+1,IINF);
    dp[0] = 0;
    for(int i=0;i<n;i++){
        dp[i+1] = min(dp[i+1],dp[i]+1);
        int m = w[i][0]-'a';
        int j = *upper_bound(pos[m].begin(), pos[m].end(), i);
        if(j < IINF){
            dp[j] = min(dp[j], dp[i]);
        }
    }
    cout << dp[n] << endl;
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 10088
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;
const int IINF = INT_MAX;
const int MAX_N = int(1e5 + 5);

int main() {
    int n, dp[MAX_N], wmin[26];
    string w[MAX_N];
    cin >> n;
    for(int i=0;i<n;i++){
        cin >> w[i];
    }
    fill(dp,dp+n+1,IINF);
    fill(wmin,wmin+26,IINF);

    dp[0] = 0;
    for(int i=0;i<n;i++){
        dp[i+1] = min(dp[i]+1, wmin[w[i][0]-'a']);
        wmin[w[i][0]-'a'] = dp[i+1];
    }
    cout << dp[n] << endl;
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 9968
final_rank: 11

code_snippet: #include<bits/stdc++.h>
using namespace std;

#define lint long long
#define P pair<int, int>
#define LLP pair<long long, long long>
#define REP(i, x, n) for(int i = (x), i##_len = (int)(n) ; i < i##_len ; ++i)
#define rep(i, n) for(int i = 0, i##_len = (int)(n) ; i < i##_len ; ++i)
#define repr(i, n) for(int i = (int)(n) - 1 ; i >= 0 ; --i)
#define SORT(x) sort((x).begin(), (x).end())
#define SORT_INV(x) sort((x).rbegin(), (x).rend())

const int IINF = 1e9 + 100;
const long long LLINF = 2e18 + 129;
const long long MOD = 1e9 + 7;
const int dx4[] = {1, 0, -1, 0}, dy4[] = {0, 1, 0, -1};
const int dx8[] = {1, 1, 0, -1, -1, -1, 0, 1}, dy8[] = {0, -1, -1, -1, 0, 1, 1, 1};
const double EPS = 1e-8;

template<typename T>
bool chmin(T &a, T b){
    if(a > b){
        a = b;
        return true;
    }else{
        return false;
    }
}

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);

    int n;
    cin >> n;

    vector<string> w(n + 1);
    REP(i, 1, n + 1){
        cin >> w[i];
    }
    w[0].clear();
    w[0].push_back(w[1][0]);

    map< pair<char, char>, int > mp;
    rep(i, n + 1){
        mp[{w[i].front(), w[i].back()}] = i;
    }

    vector< vector<int> > v(26);
    for(auto x : mp){
        v[x.first.first - 'a'].emplace_back(x.second);
    }
    rep(i, 26){
        SORT(v[i]);
    }

    vector<int> cost(n + 1, IINF);
    queue< P > que;
    que.push({0, 0});
    while(!que.empty()){
        P now = que.front();
        que.pop();
        if(!chmin(cost[now.first], now.second)){
            continue;
        }
        for(auto it = upper_bound(v[w[now.first].back() - 'a'].begin(), v[w[now.first].back() - 'a'].end(), now.first) ; it != v[w[now.first].back() - 'a'].end() ; ++it){
            if(cost[*it] > now.second + 1){
                que.push({*it, now.second + 1});
            }
        }
    }

    cout << cost[n] << endl;

    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 8912
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const ll MOD = 1000000007;
const int IINF = INT_MAX;
const ll LLINF = LLONG_MAX;
const int MAX_N = int(1e5 + 5);
const double EPS = 1e-11;
const int di[] = {0, 1, 0, -1}, dj[] = {1, 0, -1, 0};
#define REP(i, n) for (int i = 0; i < n; i++)
#define REPR(i, n) for (int i = n; i >= 0; i--)
#define SORT(v) sort((v).begin(), (v).end())
#define ALL(v) (v).begin(), (v).end()

int main() {
    int n, dp[MAX_N], premin[26];
    string s[MAX_N];
    cin >> n;
    REP(i,n) cin >> s[i];
    fill(premin,premin+26,IINF);
    fill(dp,dp+n+1,IINF);
    dp[0] = 0;
    REP(i,n){
        int c = s[i][0]-'a';
        dp[i+1] = min(dp[i]+1,premin[c]);
        premin[c] = min(premin[c],dp[i+1]);
    }
    cout << dp[n] << endl;
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 10024
final_rank: 12

code_snippet: #include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<string>
#include<vector>
#include<map>
#include<stack>
#include<queue>

using namespace std;

#define INF 1<<15

int main(){
	int N;
	int dp[100001];
	int opt[26];
	string w[100001];
	
	scanf("%d",&N);
	for(int i=0;i<N;i++) cin >> w[i];
	for(int i=0;i<N+1;i++) dp[i]=INF;
	dp[0]=0;
	for(int i=0;i<26;i++) opt[i]=INF;//alphabet's number
	
	for(int i=1;i<N+1;i++){
		int c=w[i-1].front() - 'a';
		opt[c]=min(opt[c],dp[i-1]);
		dp[i]=opt[c]+1;
	}
	printf("%d\n",dp[N]);
}
accuracy: 1
time_ms: 40
memory_kb: 10156
final_rank: 9

code_snippet: # include <iostream>
# include <algorithm>
#include <array>
# include <cassert>
#include <cctype>
#include <climits>
#include <numeric>
# include <vector>
# include <string>
# include <set>
# include <map>
# include <cmath>
# include <iomanip>
# include <functional>
# include <tuple>
# include <utility>
# include <stack>
# include <queue>
# include <list>
# include <bitset>
# include <complex>
# include <chrono>
# include <random>
# include <limits.h>
# include <unordered_map>
# include <unordered_set>
# include <deque>
# include <cstdio>
# include <cstring>
#include <stdio.h>
#include<time.h>
#include <stdlib.h>
#include <cstdint>
#include <cfenv>
#include<fstream>
//#include <bits/stdc++.h>
using namespace std;
using LL = long long;
using ULL = unsigned long long;
long long MOD = 1000000000 + 7;
constexpr long long INF = numeric_limits<LL>::max();
const double PI = acos(-1);
#define fir first
#define sec second
#define thi third
#define debug(x) cerr<<#x<<": "<<x<<'\n'
typedef pair<LL, LL> Pll;
typedef pair<LL, pair<LL, LL>> Ppll;
typedef pair<LL, pair<LL, bitset<100001>>> Pbll;
typedef pair<LL, pair<LL, vector<LL>>> Pvll;
typedef pair<LL, LL> Vec2;
struct Tll { LL first, second, third; };
struct Fll { LL first, second, third, fourth; };
typedef pair<LL, Tll> Ptll;
#define rep(i,rept) for(LL i=0;i<rept;i++)
#define Mfor(i,mf) for(LL i=mf-1;i>=0;i--)
LL h, w, n, m, k, t, s, p, q, last, first, cnt, sum, ans, dp[200000], b[300000][26];
Pll a[300000];
string str, ss;
bool f[200];
char c, ch[100][100];
int di[4][2] = { { 0,1 },{ 1,0 },{ 0,-1 },{ -1,0 } };
struct Edge { LL to, cost; };
vector<Edge>vec[200000];
vector<LL>v[26];
map<Pll,LL>ma;
multiset<LL>st;
void YN(bool f) {
	if (f)
		cout << "YES" << endl;
	else
		cout << "NO" << endl;
}
void yn(bool f) {
	if (f)
		cout << "Yes" << endl;
	else
		cout << "No" << endl;
}

int main() {
	cin >> n;
	rep(i, n) {
		cin >> str;
		a[i].first = str[0] - 'a', a[i].second = str[str.size() - 1] - 'a';
		v[a[i].first].push_back(i);
		if (i == 0) {
			first = str[0] - 'a';
		}
		if (i == n - 1) {
			last = str[0] - 'a';
		}
	}
	Mfor(i, n) {
		rep(j, 26) {
			b[i][j] = -1;
		}
	}
	Mfor(i, n - 1) {
		rep(j, 26) {
			if (a[i + 1].first == j && b[i+1][j] == -1)
				b[i][j] = i+1;
			else
				b[i][j] = max(b[i][j], b[i + 1][j]);
		}
	}
	priority_queue<Pll,vector<Pll>,greater<Pll>>qu;
	qu.push(Pll(0, 0));
	rep(i, n+1) {
		dp[i] = INF;
	}
	dp[0] = 0;
	while (!qu.empty()) {
		Pll cur = qu.top();
		qu.pop();
		LL num = cur.first, u = cur.second;
		if (num > dp[u]||u==n)continue;

		for (auto i = lower_bound(v[a[u].first].begin(), v[a[u].first].end(), u + 1); i != v[a[u].first].end(); i++) {
				if (dp[*i] > dp[u]) {
					dp[*i] = dp[u];
					qu.push(Pll(dp[*i], *i));
				}
				else {
					break;
				}
		}

		if (dp[u + 1] > dp[u] + 1) {
			dp[u + 1] = dp[u] + 1;
			qu.push(Pll(dp[u + 1], u + 1));
		}
	}
	cout << dp[n] << endl;
	return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 33908
final_rank: 20

code_snippet: #include<iostream>
#include<string>

using namespace std;

int main(){
    int n;
    cin >> n;
    string s[n+1];
    for(int i=1;i<=n;i++) cin >> s[i];

    int dp[n+1], dpmin[26];
    fill(dpmin, dpmin+26, n);
    dpmin[s[1][0]-'a'] = 0;
    for(int i=1;i<=n;i++){
        char start_char = s[i][0], end_char = s[i][s[i].length()-1];
        dp[i] = dpmin[start_char-'a'] + 1;
        dpmin[end_char-'a'] = min(dpmin[end_char-'a'], dp[i]);
    }

    cout << dp[n] << endl;
}
accuracy: 1
time_ms: 40
memory_kb: 10004
final_rank: 7

code_snippet: #include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<b;i++)
#define rrep(i,a,b) for(int i=a;i>=b;i--)
#define fore(i,a) for(auto &i:a)
#define all(x) (x).begin(),(x).end()
#pragma GCC optimize ("-O3")
using namespace std; void _main(); int main() { cin.tie(0); ios::sync_with_stdio(false); _main(); }
typedef long long ll; const int inf = INT_MAX / 2; const ll infl = 1LL << 60;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a = b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a = b; return 1; } return 0; }
//---------------------------------------------------------------------------------------------------
/*---------------------------------------------------------------------------------------------------
　　　　　　　　　　　 ∧＿∧  
　　　　　 ∧＿∧ 　（´<_｀ ）　 Welcome to My Coding Space!
　　　　 （ ´_ゝ`）　/　 ⌒i     
　　　　／　　　＼　 　 |　|     
　　　 /　　 /￣￣￣￣/　　|  
　 ＿_(__ﾆつ/　    ＿/ .| .|＿＿＿＿  
　 　　　＼/＿＿＿＿/　（u　⊃  
---------------------------------------------------------------------------------------------------*/



int N;
string W[101010];
int dp[101010], opt[101];
//---------------------------------------------------------------------------------------------------
void _main() {
    cin >> N;
    rep(i, 0, N) cin >> W[i];

    rep(i, 0, N + 1) dp[i] = inf;
    dp[0] = 0;
    rep(i, 0, 26) opt[i] = inf;

    rep(i, 1, N + 1) {
        int c = W[i - 1].front() - 'a';
        chmin(opt[c], dp[i - 1]);
        
        dp[i] = opt[c] + 1;
    }

    cout << dp[N] << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 9276
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;

int now[27];
int dp[100005] = {0};
int n;
string s, dummy;

int solve();

int main() {
  int i;
  cin >> n;
  for(i = 0; i < n; ++i) {
    cin >> dummy;
    s += dummy[0];
  }
  for(i = 0; i < 26; ++i) now[i] = -1000000000;
  cout << solve() << endl;
  return 0;
}

int solve() {
  int i, j, nown;
  for(i = 0; i < n; ++i) {
    nown = s[i] - 'a';
    now[nown] = max(now[nown], dp[max(i - 1, 0)]);
    if(i != 0) dp[i] = max(dp[i - 1], now[nown]);
    for(j = 0; j < 26; ++j) ++now[j];
  }
  return n - dp[n - 1];
}
accuracy: 1
time_ms: 30
memory_kb: 3720
final_rank: 6

code_snippet: #include <iostream>
#include <string>
#include <vector>
using namespace std;

vector<vector<int> > calcNext(const string &S) {
    int n = (int)S.size();
    vector<vector<int> > res(n, vector<int>(26, n));
    for (int i = n-2; i >= 0; --i) {
        for (int j = 0; j < 26; ++j) res[i][j] = res[i+1][j];
        res[i][S[i+1]-'a'] = i+1;
    }
    return res;
}

int main() {
    int N; cin >> N;
    string S = "";
    for (int i = 0; i < N; ++i) {
        string word; cin >> word;
        S += word[0];
    }
    auto next = calcNext(S);
    vector<int> dp(N+1, N);
    dp[0] = 1;
    for (int i = 0; i < N; ++i) {
        dp[i+1] = min(dp[i+1], dp[i]+1);
        int ni = next[i][S[i]-'a'];
        if (ni >= N) continue;
        dp[ni] = min(dp[ni], dp[i]);
    }
    cout << dp[N-1] << endl;
}
accuracy: 1
time_ms: 70
memory_kb: 16568
final_rank: 17

code_snippet: #include <bits/stdc++.h>
#define GET_MACRO(_1,_2,_3,_4,_5,_6,_7,_8,NAME,...) NAME
#define pr(...) cerr<< GET_MACRO(__VA_ARGS__,pr8,pr7,pr6,pr5,pr4,pr3,pr2,pr1)(__VA_ARGS__) <<endl
#define pr1(a) (#a)<<"="<<(a)<<" "
#define pr2(a,b) pr1(a)<<pr1(b)
#define pr3(a,b,c) pr1(a)<<pr2(b,c)
#define pr4(a,b,c,d) pr1(a)<<pr3(b,c,d)
#define pr5(a,b,c,d,e) pr1(a)<<pr4(b,c,d,e)
#define pr6(a,b,c,d,e,f) pr1(a)<<pr5(b,c,d,e,f)
#define pr7(a,b,c,d,e,f,g) pr1(a)<<pr6(b,c,d,e,f,g)
#define pr8(a,b,c,d,e,f,g,h) pr1(a)<<pr7(b,c,d,e,f,g,h)
using namespace std;
using Int = long long;
using _int = int;
using ll = long long;
using Double = long double;
const Int INF = (1LL<<55)+1e9; // ~ 3.6 * 1e16
const Int mod = (1e9)+7;
const Double EPS = 1e-8;
const Double PI = 6.0 * asin((Double)0.5);
using P = pair<Int,Int>;
using T = tuple<Int,Int,Int>;
template<class T> T Max(T &a,T b){return a=max(a,b);}
template<class T> T Min(T &a,T b){return a=min(a,b);}
template<class T1, class T2> ostream& operator<<(ostream& o,pair<T1,T2> p){return o<<"("<<p.first<<","<<p.second<<")";}
template<class T1, class T2, class T3> ostream& operator<<(ostream& o,tuple<T1,T2,T3> t){
  return o<<"("<<get<0>(t)<<","<<get<1>(t)<<","<<get<2>(t)<<")";}
template<class T1, class T2> istream& operator>>(istream& i,pair<T1,T2> &p){return i>>p.first>>p.second;}
template<class T> ostream& operator<<(ostream& o,vector<T> &a){Int i=0;for(T t:a)o<<(i++?" ":"")<<t;return o;}
template<class T> istream& operator>>(istream& i,vector<T> &a){for(T &t:a)i>>t;return i;}
template<class T>void prArr(T a,string s=" "){Int i=0;for(auto t:a)cout<<(i++?s:"")<<t;cout<<endl;}


signed main(){
  srand((unsigned)time(NULL));
  cin.tie(0);
  ios_base::sync_with_stdio(0);
  cout << fixed << setprecision(12);

  Int n;
  cin>>n;

  vector<string> A(n);
  cin>>A;

  vector<Int> dp(30,INF);
  dp[A[0][0] - 'a'] = 1;
  for(Int i=1;i<n;i++) Min(dp[A[i][0] - 'a'], dp[A[i-1][0] - 'a'] + 1);
  Int ans = dp[A[n-1][0] - 'a'];
  cout<<ans<<endl;
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 8460
final_rank: 1

code_snippet: #include <bits/stdc++.h>
                                            #include<iostream>
                                            #include<cstdio>
                                            #include<vector>
                                            #include<queue>
                                            #include<map>
                                            #include<cstring>
                                            #include<string>
                                            #include <math.h>
                                            #include<algorithm>
                                        //    #include <boost/multiprecision/cpp_int.hpp>
                                            #include<functional>
                                   #define int long long
                                            #define inf  1000000007
                                            #define pa pair<int,int>
                                            #define ll long long
                                            #define pal pair<double,double>
                                            #define ppap pair<pa,int>
                                    //  #define PI 3.14159265358979323846
                                            #define paa pair<int,char>
                                            #define  mp make_pair
                                            #define  pb push_back
                                            #define EPS (1e-10)
                                            #define equals(a,b) (fabs((a)-(b))<EPS)
    int dx[8]={0,-1,0,1,1,1,-1,-1};
    int dy[8]={1,0,-1,0,-1,1,1,-1};
                                            using namespace std;
                                   			class pa3{
                                            	public:
                                            	int x,y,z;
                                            	pa3(int x=0,int y=0,int z=0):x(x),y(y),z(z) {}
                                            	bool operator < (const pa3 &p) const{
                                            		if(x!=p.x) return x<p.x;
                                            		if(y!=p.y) return y<p.y;
                                            		 return z<p.z;
                                            		//return x != p.x ? x<p.x: y<p.y;
                                            	}
                                   				bool operator > (const pa3 &p) const{
                                            		if(x!=p.x) return x>p.x;
                                            		if(y!=p.y) return y>p.y;
                                            		 return z>p.z;
                                            		//return x != p.x ? x<p.x: y<p.y;
                                            	}
                                            	bool operator == (const pa3 &p) const{
                                            		return x==p.x && y==p.y && z==p.z;
                                            	}
                                            		bool operator != (const pa3 &p) const{
                                            			return !( x==p.x && y==p.y && z==p.z);
                                            	}
                                            
                                            };
                                            
                                            class pa4{
                                            	public:
                                            	double x;
                                            	int y,z,w;
                                            	pa4(double x=0,int y=0,int z=0,int w=0):x(x),y(y),z(z),w(w) {}
                                            	bool operator < (const pa4 &p) const{
                                            		if(x!=p.x) return x<p.x;
                                            		if(y!=p.y) return y<p.y;
                                            		if(z!=p.z)return z<p.z;
                                            		return w<p.w;
                                            		//return x != p.x ? x<p.x: y<p.y;
                                            	}
                                            	bool operator > (const pa4 &p) const{
                                            		if(x!=p.x) return x>p.x;
                                            		if(y!=p.y) return y>p.y;
                                            		if(z!=p.z)return z>p.z;
                                            		return w>p.w;
                                            		//return x != p.x ? x<p.x: y<p.y;
                                            	}
                                            	bool operator == (const pa4 &p) const{
                                            		return x==p.x && y==p.y && z==p.z &&w==p.w;
                                            	}
                                            		
                                            
                                            };
                                            class pa2{
                                            	public:
                                            	int x,y;
                                            	pa2(int x=0,int y=0):x(x),y(y) {}
                                            	pa2 operator + (pa2 p) {return pa2(x+p.x,y+p.y);}
                                            	pa2 operator - (pa2 p) {return pa2(x-p.x,y-p.y);}
                                            	bool operator < (const pa2 &p) const{
                                            		return y != p.y ? y<p.y: x<p.x;
                                            	}
                                            	bool operator > (const pa2 &p) const{
                                            		return x != p.x ? x<p.x: y<p.y;
                                            	}
                                            	bool operator == (const pa2 &p) const{
                                            		return abs(x-p.x)==0 && abs(y-p.y)==0;
                                            	}
                                            	bool operator != (const pa2 &p) const{
                                            		return !(abs(x-p.x)==0 && abs(y-p.y)==0);
                                            	}
                                            		
                                            
                                            };
                             string itos( int i ) {
                                ostringstream s ;
                                s << i ;
                                return s.str() ;
                                }
                                 
                                int gcd(int v,int b){
                                	if(v>b) return gcd(b,v);
                                	if(v==b) return b;
                                	if(b%v==0) return v;
                                	return gcd(v,b%v);
                                }
                 
                   
                
                    /*
                                                   #define ppa pair<int,pas>
                                            class Point{
                                            	public:
                                            	double x,y;
                                            	Point(double x=0,double y=0):x(x),y(y) {}
                                            	Point operator + (Point p) {return Point(x+p.x,y+p.y);}
                                            	Point operator - (Point p) {return Point(x-p.x,y-p.y);}
                                            	Point operator * (double a) {return Point(x*a,y*a);}
                                            	Point operator / (double a) {return Point(x/a,y/a);}
                                            	double absv() {return sqrt(norm());}
                                            	double norm() {return x*x+y*y;}
                                            	bool operator < (const Point &p) const{
                                            		return x != p.x ? x<p.x: y<p.y;
                                            	}
                                            	bool operator == (const Point &p) const{
                                            		return fabs(x-p.x)<EPS && fabs(y-p.y)<EPS;
                                            	}
                                            };
                                            typedef Point Vector;
                                     #define pl pair<int,pas>
                                            struct Segment{
                                            Point p1,p2;
                                            };
                                             double dot(Vector a,Vector b){
                                            	return a.x*b.x+a.y*b.y;
                                            }
                                            double cross(Vector a,Vector b){
                                            	return a.x*b.y-a.y*b.x;
                                            }
                                        
                bool parareru(Point a,Point b,Point c,Point d){
                //	if(abs(cross(a-b,d-c))<EPS)cout<<"dd "<<cross(a-b,d-c)<<endl;
                	return abs(cross(a-b,d-c))<EPS;
                }
                double distance_ls_p(Point a, Point b, Point c) {
                  if ( dot(b-a, c-a) < EPS ) return (c-a).absv();
                  if ( dot(a-b, c-b) < EPS ) return (c-b).absv();
                  return abs(cross(b-a, c-a)) / (b-a).absv();
                }
                bool is_intersected_ls(Segment a,Segment b) {
                	if(a.p1==b.p1||a.p2==b.p1||a.p1==b.p2||a.p2==b.p2) return false;
                	if(parareru((a.p2),(a.p1),(a.p1),(b.p2))&&parareru((a.p2),(a.p1),(a.p1),(b.p1))){
                //		cout<<"sss"<<endl;
                		if(dot(a.p1-b.p1,a.p1-b.p2)<EPS) return true;
                		if(dot(a.p2-b.p1,a.p2-b.p2)<EPS) return true;
                		if(dot(a.p1-b.p1,a.p2-b.p1)<EPS) return true;
                		if(dot(a.p1-b.p2,a.p2-b.p2)<EPS) return true;
                		return false;
                	}
                  else return ( cross(a.p2-a.p1, b.p1-a.p1) * cross(a.p2-a.p1, b.p2-a.p1) < EPS ) && ( cross(b.p2-b.p1, a.p1-b.p1) * cross(b.p2-b.p1, a.p2-b.p1) < EPS );
                }
                 
                double segment_dis(Segment a,Segment b){
                	if(is_intersected_ls(a,b))return 0;
                	double r=distance_ls_p(a.p1, a.p2, b.p1);
                	r=min(r,distance_ls_p(a.p1, a.p2, b.p2));
                	r=min(r,distance_ls_p(b.p1, b.p2, a.p2));
                	r=min(r,distance_ls_p(b.p1, b.p2, a.p1));
                	return r;
                }
                Point intersection_ls(Segment a, Segment b) {
                  Point ba = b.p2-b.p1;
                  double d1 = abs(cross(ba, a.p1-b.p1));
                  double d2 = abs(cross(ba, a.p2-b.p1));
                  double t = d1 / (d1 + d2);
                 
                  return a.p1 + (a.p2-a.p1) * t;
                }
                 
                                double distans(double x1,double y1,double x2,double y2){
                                	double rr=(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
                                	return sqrt(rr);
                                	
                                }
                 */
                                int mod;
                
                int beki(int wa,int rr,int warukazu){
                	if(rr==0) return 1%warukazu;
                	if(rr==1) return wa%warukazu;
                	if(rr%2==1) return (beki(wa,rr-1,warukazu)*wa)%warukazu;
                	int zx=beki(wa,rr/2,warukazu);
                	return (zx*zx)%warukazu;
                }
              /*  
    double bekid(double w,int r){
    	if(r==0) return 1.0;
    	if(r==1) return w;
    	if(r%2) return bekid(w,r-1)*w;
    	double f=bekid(w,r/2);
    	return f*f;
    }
                               
                int pr[500010];
                int inv[500010];
              
                
    			int comb(int nn,int rr){
    				int r=pr[nn]*inv[rr];
    				r%=mod;
    				r*=inv[nn-rr];
    				r%=mod;
    				return r;
    			}
                
                void gya(int ert){
                	pr[0]=1;
                	for(int i=1;i<ert;i++){
                		pr[i]=(pr[i-1]*i)%mod;
                	}
                	for(int i=0;i<ert;i++) inv[i]=beki(pr[i],mod-2,mod);
                	
                }
                
                */
                
              //   cin.tie(0);
    		//	ios::sync_with_stdio(false);
    			//priority_queue<pa3,vector<pa3>,greater<pa3>> pq;            
                 //sort(ve.begin(),ve.end(),greater<int>());
                                         //----------------kokomade tenpure------------
                //vector<double> ans(100000000),ans2(100000000)

int dp[26];
vector<string> ve;
    signed main(){
     
    	       cin.tie(0);
    			ios::sync_with_stdio(false); 
int n;
cin>>n;
    	for(int i=0;i<26;i++)dp[i]=inf;
    	for(int i=0;i<n;i++){
    		string t;
    		cin>>t;
    		ve.pb(t);
    	}
    	reverse(ve.begin(),ve.end());
    	
    	for(int i=0;i<n;i++){
    		if(i==0){
    			dp[ve[i][0]-'a']=1;
    		}
    		else{
    			dp[ve[i][0]-'a']=min(dp[ve[i].back()-'a']+1,dp[ve[i][0]-'a']);
    			
    		}
    		if(i==n-1){
    			cout<<dp[ve[i][0]-'a']<<endl;
    			return 0;
    		}
    	}
    	
    	
    	return 0;
    }
accuracy: 1
time_ms: 10
memory_kb: 8508
final_rank: 2

code_snippet: #include "bits/stdc++.h"
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int INF = 1e9;
const ll LINF = 1e18;
template<class S,class T> ostream& operator << (ostream& out,const pair<S,T>& o){ out << "(" << o.first << "," << o.second << ")"; return out; }
template<class T> ostream& operator << (ostream& out,const vector<T> V){ for(int i = 0; i < V.size(); i++){ out << V[i]; if(i!=V.size()-1) out << " ";} return out; }
template<class T> ostream& operator << (ostream& out,const vector<vector<T> > Mat){ for(int i = 0; i < Mat.size(); i++) { if(i != 0) out << endl; out << Mat[i];} return out; }
template<class S,class T> ostream& operator << (ostream& out,const map<S,T> mp){ out << "{ "; for(auto it = mp.begin(); it != mp.end(); it++){ out << it->first << ":" << it->second; if(mp.size()-1 != distance(mp.begin(),it)) out << ", "; } out << " }"; return out; }

/*
 <url:https://onlinejudge.u-aizu.ac.jp/services/room.html#ACPC2018Day3/problems/D>
 問題文============================================================
 =================================================================
 解説=============================================================
 ================================================================
 */

const int MAXN = 100005;
vector<pii> G[MAXN*2];
int dist[MAXN*2];
vector<int> verbose[26];

ll solve(){
    ll res = 0;
    int N; cin >> N;
    for(int i = 0; i < N;i++){
        string str; cin >> str;
        verbose[str.front()-'a'].push_back(i);
    }
    for(int i = 0; i < N;i++) G[i].push_back({i+1,1});
    for(int i = 0; i < 26;i++){
        for(int j = 0; j < verbose[i].size();j++){
            G[verbose[i][j]].push_back({verbose[i][j]+N+1,0});
            G[verbose[i][j]+N+1].push_back({verbose[i][j]+1,1});
            if(j != 0){
                G[verbose[i][j-1]+N+1].push_back({verbose[i][j]+N+1,0});
            }
        }
        
    }
    queue<int> q;
    fill(dist,dist+2*(N+1),INF);
    dist[0] = 0; q.push(0);
    while(q.size()){
        int n = q.front(); q.pop();
        for(const pii& e:G[n]){
            if(dist[e.first] > dist[n]+e.second){
                dist[e.first] = dist[n] + e.second;
                q.push(e.first);
            }
        }
    }
    res = dist[N];
    return res;
}
int main(void) {
    cin.tie(0); ios_base::sync_with_stdio(false);
    cout << solve() << endl;
    return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 15040
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define int long long
#define REPF(i, a, n) for (int i = a; i < (n); i++)
#define REP(i, n) REPF(i, 0, n)
#define FORE(x, s) for (auto& x : s)
#define ALL(x) begin(x),end(x)
#define SZ(x) ((int)x.size())
template<class T> bool chmax(T&a, const T& b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}

signed main() {
    int N;
    cin >> N;
    vector<string> w(N);
    REP(i, N) cin >> w[i];
    vector<vector<int>> idx(26);
    vector<int> num(N);
    REP(i, N) {
        int ch = w[i][0] - 'a';
        num[i] = SZ(idx[ch]);
        idx[ch].push_back(i);
    }

    vector<int> dp(N + 1);
    int mx = 0;
    REP(i, N) {
        int ch = w[i][0] - 'a';
        chmax(mx, dp[i]);
        dp[i] = mx;
        // cerr << "i = " << i << ", dp[i] = " << dp[i] << endl;
        if (num[i] + 1 < SZ(idx[ch])) {
            chmax(dp[idx[ch][num[i] + 1]], dp[i] + (idx[ch][num[i] + 1] - idx[ch][num[i]]));
        }
    }
    cout << N - mx << endl;
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 11992
final_rank: 14