【AtCoder】ABC141E Who Says a Pun?

問題

https://atcoder.jp/contests/abc141/tasks/abc141_e
Sの連続する部分文字列として重ならずに2回以上現れるもののうち長さが最も長いものを求める問題。

editorialでは「Z-Algorithm」や「ローリングハッシュと平衡二分探索木」などが使われていたが、割とシンプルな別解があったので書きました。

解法 ~ずらし方を全探索~

与えられた文字列Sと、Sをiだけずらした文字列を考える。
(要するに、S[0],S[1],S[2],…とS[i],S[i+1],S[i+2],…を比較していくということ。)
この2つの共通部分列の最大長をO(N)で求められれば、1<=i<=N-1を全部試すことでO(N^2)で求められる。
SとSをiだけずらした文字列の共通部分列の最大長は、文字列を端から見て、同じなら答えに+1して、異なるなら0にリセットするのを繰り返せばよい。
が、注意すべき点があって、「2つの部分文字列が重ならない」という条件を考えると、答えはi以下であるので、その比較も忘れずに行う。

N = int(input())
S = input()
ans = 0
# iだけずらす
for i in range(1,N):
    # iだけずらしたときの最長連続部分列の長さ
    c = 0
    cc = 0
    for j in range(N-i):
        if S[j] == S[i+j]:
            cc += 1
        else:
            c = max(cc,c)
            cc = 0
    c = max(cc,c)
    # iだけずらしたならcの最大値はi
    c = min(i,c)
    ans = max(ans,c)
print(ans)

ところでこのコードの可読性ひどすぎませんか?許してください。
Z-Algorithmは前々からちゃんと勉強しようと思っていたのでこの機会にやろうと思います。